Setup Guru Notebook on [[TiddlySpot|www.tiddlyspot.com]]
Decided to use Camino for TiddlyWiki. Finally set it up.
''Syntax:''\n|[//action// [//actionParameters//]]|\n\nThe Action Specification in the [[ForEachTiddlerMacro]] specifies what should happen with the tiddlers. The specified action is applied to all tiddlers that are selected through the [[whereClause]], in the order specified by the [[sortClause]]. \n\nThe following actions are supported:\n\n<<tiddler AddToListAction>>\n<<tiddler WriteAction>>\n
''//The {{{addToList}}} action//''\n\nThe {{{addToList}}} action of the ForEachTiddlerMacro adds every selected tiddler to a list and displays it at the location of the macro.\n\nIt is the default action, i.e when no action is given the addToList action is used.\n
Here are some examples that show the usage of the addToList action (the default action) in the ForEachTiddlerMacro.\n<<forEachTiddler\n where\n 'tiddler.tags.contains("addToListActionExample")'\n>>\nSee also ForEachTiddlerExamples.
config.options.chkHttpReadOnly = false;\n
!HowTo\n*[[Apache2-SSL-PHP5-Howto (+ Zend Optimizer And IonCube Loader)|http://www.howtoforge.com/linux_apache2_ssl_php5_zendoptimizer_ioncubeloader]]\n\n!Virtual Server HTTP to HTTPS redirection\n{{{\n<VirtualHost mywebserver:8080>\n<IfModule mod_ssl.c>\nSSLEngine on\nSSLCertificateFile /xx/xxx/xxx.crt\nSSLCertificateKeyFile /xx/xxx/xxx.key\nSetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown\n</IfModule>\nServerName mywebserver\nDocumentRoot /xxx/xxx/xxx/xxx\n<Directory /xxx/xxx/xxx/xxx>\nOptions Indexes FollowSymLinks MultiViews +ExecCGI\nAllow from all\n</Directory>\n</VirtualHost>\n}}}\n\n!How to redirect from http to https\nYou'll have to run another virtual server on another\nport. Then redirect to your https server. You can't\nrun http/https on the same port. Suggest 8080 as http\nand 8443 as https. Then ...\n{{{\nRewriteEngine On\nRewriteLog "logs/rewrite.log"\nRewriteLogLevel 0\nRewriteRule ^/(.*) https://xxxx:8443/$1 [R=301,L]\n}}}\n\n!Quick SSL Certificate creation - see OpenSSL for the proper way to do this\nIf we want to start up our Apache2 with SSL support we have to generate the file /etc/httpd/ssl.crt/server.crt because otherwise we will get an error message when we start Apache2.\n{{{\nmkdir /etc/httpd/ssl.crt\nopenssl genrsa -des3 -passout pass:asecretpassword -out /etc/httpd/ssl.crt/server.key.org 1024\nopenssl req -new -passin pass:asecretpassword -passout pass:asecretpassword -key /etc/httpd/ssl.crt/server.key.org -out /etc/httpd/ssl.crt/server.csr -days 3650\nopenssl req -x509 -passin pass:asecretpassword -passout pass:asecretpassword -key /etc/httpd/ssl.crt/server.key.org -in /etc/httpd/ssl.crt/server.csr -out /etc/httpd/ssl.crt/server.crt -days 3650\nopenssl rsa -passin pass:asecretpassword -in /etc/httpd/ssl.crt/server.key.org -out /etc/httpd/ssl.crt/server.key\nmkdir /etc/httpd/ssl.key\nmv /etc/httpd/ssl.crt/server.key /etc/httpd/ssl.key/server.key\nchmod 400 /etc/httpd/ssl.key/server.key\n}}}\n(Please note: It is safe to accept the default values for all the questions you see when you create /etc/httpd/ssl.crt/server.crt because in either case you will receive a warning in your browser if you try to access an SSL site on your server:\n\nIf you do not want to get this warning you will have to get a "real" SSL certificate (but this is not for free!). Have a look at the following sites:\n\n * http://www.instantssl.com/ (Recommended by the original author of this section)\n * http://www.verisign.com/\n * http://www.thawte.com/\n * http://www.baltimore.com/\n * http://www.ipsca.com/\n * http://www.entrust.com/\n * http://www.geotrust.com/ )\n
[[MacScripter.net - AppleScript Tutorials Site|http://macscripter.net/]]\n[[iTunes Playlist Manipulation Tutorial|http://macscripter.net/articles/434_0_10_0_C/]]\n[[AppleScript Language Guide|http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/index.html]]\n[[The Applescript Sourcebook|http://applescriptsourcebook.com/]]\n[[Apple Script Transactions|http://applescriptsourcebook.com/viewtopic.php?id=17527]]\n[[Run Handlers||http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/index.html]]\n[[Idle Handlers||http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/AppleScript.e7.html]]\n[[Common Value Class Definitions||http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/index.html?http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/AppleScript.fb.html#21170]]\n[[Common Scripting Tasks||http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/index.html?http://developer.apple.com/documentation/AppleScript/Conceptual/AppleScriptLangGuide/AppleScript.fb.html#21170]]\n[[Technical Note TN2065 do shell script||http://developer.apple.com/technotes/tn2002/tn2065.html]]
!Set system-wide scaling\nTo change the scale for the entire system, type the following in a Terminal window, then press Return:\n{{{defaults write NSGlobalDomain AppleDisplayScaleFactor 0.5}}}\n\nThe number at the end, 0.5, is the scale factor. I would not recommend using a value lower than 0.5 (or 50 percent), as it will otherwise become very difficult to read things. A value less than one will reduce the scale; values over one will increase the scale. For instance, this would set the system-wide scale to 125 percent:\n{{{defaults write NSGlobalDomain AppleDisplayScaleFactor 1.25}}}\n\nAfter executing this command, absolutely nothing will appear to have changed… until you launch your next application, and the one after that, and the one after that. That’s right; the command only affects programs launched after it’s been run. This can cause some weird results as you switch between apps running at 100 percent, and newly-launched apps running at your chosen scale value. You should probably logout and login again to get all your apps (including the Finder) running at the same scale.\nAfter you’re done experimenting with this, if you want to reset everything back to normal in Terminal, it’s easy to do with this command:\n{{{defaults write NSGlobalDomain AppleDisplayScaleFactor 1}}}\n\nThis sets the scale back to 100 percent, and again, you’ll want to logout and login to get all the apps back to normal.\n!Set scaling per application\nTo change only a given application’s scale factor, you just need to use a modified version of the above command. iTunes, for instance, can be scaled down with this command (quit iTunes first):\n{{{defaults write com.apple.iTunes AppleDisplayScaleFactor .75}}}\n
[[HowTo: Replacing SkypeOut with Asterisk and a softphone.|http://www.eissq.com/HowTo_Asterisk_SkypeOut.html]]\n[[Astmasters HOW-TOs|http://www.astmasters.net/howtos.html#localhost-gw]]\n[[Building Asterisk on MacOSX|http://www.voip-info.org/wiki/view/Building+Asterisk+on+MacOSX]]\n[[Asterisk MacOSX Support|http://www.voip-info.org/wiki/index.php?page=Asterisk+MacOSX+Support]]\n\n!SIP ATA Device\nGrandstream is about $25/port for 2\n$100 for 4 phone extensions\nGrandstream ATA will register with and SIP VOIP provider you sign up with\n\n!VOIP Provider Setup\nRegister ATA device locally to [[Asterisk switch|www.asterisk.org]] and trunk to voicepulse\nTerminate with IAX trunk (which Asterisk can) to connect.voicepulse.com and get 4 inbound lines for $11/month (Outbound is rated)\nHave auto attendant pick up, have extensions, conferencing, web voicemail, and CDR right out of the box (trixbox... google it)\nWith your own switch you can pick your provider, have multiple, and dictate routing based on cost\nSend toll calls free through [[FWD|http://www.freeworlddialup.com/]] for nothing\nUse free 411 (1-800-FREE-411) all the time\n
!MacOSX\nhttp://www.bombich.com/mactips/automount.html\nhttp://www.macosxhints.com/article.php?story=20031022164821984\n\n!Linux\nIn my LAN I have a server in which all the /home for users reside. The /home \nis shared via NFS. The server also as a NIS server. The server is running \nCentos 4.1.\n\nOther machines (including my desktop) in the LAN mount the /home from the \nserver, using automount. \n\nHere is /etc/auto.master:\n{{{\n/home /etc/auto.home\n}}}\nand /etc/auto.home:\n{{{\n* -rw,intr,soft,timeo=300,tcp,rsize=32768,wsize=32768 server1:/home/&\n}}}
{{{\n###########################################################\n# A startup item has been generated that will aid in\n# starting boxbackup with launchd. It is disabled\n# by default. Execute the following command to start it,\n# and to cause it to launch at startup:\n#\n# sudo launchctl load -w /Library/LaunchDaemons/org.macports.BoxBackup.plist\n###########################################################\n---> Installing boxbackup 0.10_0\n---> Activating boxbackup 0.10_0\nWarning: /opt/local/etc/box/bbackupd.conf is missing!\nYou need to run 'bbackupd-config' to create it.\nSee the documentation on client setup for details:\n file:///opt/local/share/doc/boxbackup/client.html\n}}}
/%CSS syntax attribute reference chart%/\n{{menubox{{{small{\n~~Source: Paul Petterson~~\n|>|>| !Selectors |\n| ''Selector'' | ''Sample'' | ''Description'' |\n| tag | H1 { color: blue ; } |Selects all of the specified HTML tags |\n| class | .myClass { color: blue; } |Selects all HTML tags with the attribute class="myClass" specified |\n| ID | #tag56 { color: blue; } |Selects the single HTML tag with the attibute ID="tag56" specified |\n| Grouping | H1, H2, H3 { color: blue ; } | selects all specified selectors (tags, class, or ID can be specified) |\n| Contextual | H1 B { color: red; } |selects all 'B' tags in H1. Context selectors can be tag, class, or ID selectors |\n\n|>|>|>| !Units |\n| ''Type'' | ''Unit'' | ''Description'' |\n| Length | mm, cm, in |millimeters, centimeters, inches |\n|~| pt, pc |point size, pica |\n|~| em, ex |relative to the point size of the font, relative to x-height of the font |\n|~| px |pixel (device dependent) |\n| Percentage | % |calculated as a percentage of their default size used in context |\n| Keywords | .. | ... |\n| Color | <name> |Color names ex: green see: ColorNames |\n|~| rgb() |specify number or percengate rgb(100%, 0, 100%) |\n|~| <hex value> |specify hex RGB number of color ex: #00FF00 see: ColorChart |\n\n|>|>|>| !Font Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| font-family |[font name or type] | font-family: Verdana, Arial; | Y |\n| font-style |normal, italic | font-style:italic; | Y |\n| font-variant |normal, small-cap | font-variant:small-caps; | Y |\n| font-weight |normal, bold | font-weight:bold; | Y |\n| font-size |[ xx-large, x-large, large, medium, small, x-small, xx-small ], [ larger, smaller ], \s\spercentage'\s\s, //length// | font-size:12pt; | Y |\n| font |[//font-style// / //font-variant// / //font-weight//] ? //font-size// [//line-height//] ? //font-family// | font: bold 12pt Arial; | Y |\n\n|>|>|>| !Color and Background Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| color |//color // | color: red | Y |\n| background-color |//color//, transparent | background-color: yellow | N* |\n| background-image |//url//, none | background-image: url(house.jpg)| N* |\n| background-repeat |repeat, repeat-x, repeat-y, no-repeat | background-repeat: no-repeat | N* |\n| background-attachment |scroll, fixed | background-attachment: fixed | N* |\n| background-position |[ //position// , //length// ], {1,2}, [ top, center, bottom ] -or- [ left, center, right ] | background-position: top center | N* |\n| background |transparent, //color// -or- //url// -or- repeat -or- scroll -or- //position// | background: silver url(house.jpg) repeat-y | N* |\n|>|>|>| !*Starting in CSS2, these properties are inherited. |\n\n|>|>|>| !Text Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| letter-spacing |normal, //length// | letter-spacing:5pt | Y |\n| text-decoration |none, underline, overline, line-through | text-decoration:underline | N |\n| vertical-align |sub, super, | vertical-align:sub | N |\n| text-transform |capitalize, uppercase, lowercase, none | text-transform:lowercase | N |\n| text-align |left, right, center, justify | text-align:center | N |\n| text-indent |//length//, //percentage// | text-indent:25px | N |\n| line-height |normal, //number//, //length//, //percentage// | line-height:15pt | N |\n\n\n''The //CSS Box//''\n<html>\n<div style="color:black;background-color:#FFFFCC;padding:1em;border:thin solid black;text-align:center;width=30%">margin\n<div style="color:white;background-color:black;padding:1em;border:thin solid black;text-align:center;width=100%">border\n<div style="color:black;background-color:#FFCC99;padding:1em;border:thin solid black;text-align:center;width=100%">padding\n<div style="color:black;background-color:white;border:thin solid black;text-align:center;width=100%">content<br/>\n<div style="float:left"><-</div><div style="float:right">-></div>CSS 'width'\n</div>\n</div>\n</div>\n</div>\n</html>\n\n\n|>|>|>| !Box Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| margin-top |//length//, //percentage//, auto | margin-top:5px | N |\n| margin-right |//length//, //percentage//, auto | margin-right:5px | N |\n| margin-bottom |//length//, //percentage//, auto | margin-bottom:1em | N |\n| margin-left |//length//, //percentage//, auto | margin-left:5pt | N |\n| margin |//length//, //percentage//, auto {1,4}| margin: 10px 5px 10px 5px | N |\n| padding-top |//length//, //percentage// | padding-top:10%| N |\n| padding-right |//length//, //percentage// | padding-right:15px | N |\n| padding-bottom |//length//, //percentage// | padding-bottom:1.2em | N |\n| padding-left |//length//, //percentage// | padding-left:10pt; } | N |\n| padding |//length//, //percentage// {1,4}| padding: 10px 10px 10px 15px | N |\n| border-top-width |thin, medium, thick, //length// | border-top-width:thin | N |\n| border-right-width |thin, medium, thick, //length// | border-right-width:medium | N |\n| border-bottom-width |thin, medium, thick, //length// | border-bottom-width:thick | N |\n| border-left-width |thin, medium, thick, //length// | border-left-width:15px | N |\n| border-width |thin, medium, thick, //length// {1,4}| border-width: 3px 5px 3px 5px | N |\n| border-top-color |//color // | border-top-color:navajowhite | N |\n| border-right-color |//color// | border-right-color:whitesmoke | N |\n| border-bottom-color |//color// | border-bottom-color:black | N |\n| border-left-color |//color// | border-left-color:#C0C0C0 | N |\n| border-color |//color// {1,4} | border-color: green red white blue; } | N |\n| border-top-style |none, solid, double, groove, ridge, inset, outset | border-top-style:solid | N |\n| border-right-style |none, solid, double, groove, ridge, inset, outset | border-right-style:double | N |\n| border-bottom-style |none, solid, double, groove, ridge, inset, outset | border-bottom-style:groove | N |\n| border-left-style |none, solid, double, groove, ridge, inset, outset | border-left-style:none | N |\n| border-style |none, solid, double, groove, ridge, inset, outset | border-style:ridge; }| N |\n| border-top |//border-width//, //border-style//, //border-color// | border-top: medium outset red | N |\n| border-right |//border-width//, //border-style//, //border-color// | border-right: thick inset maroon | N |\n| border-bottom |//border-width//, //border-style//, //border-color// | border-bottom: 10px ridge gray | N |\n| border-left |//border-width//, //border-style//, //border-color// | border-left: 1px groove red | N |\n| border |//border-width//, //border-style//, //border-color// | border: thin solid blue | N |\n| float |none, left, right | float:none | N |\n| clear |none, left, right, both | clear:left | N |\n\n|>|>|>| !Classification Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| display |none, block, inline, list-item | display:none | N |\n| list-style-type |disk, circle, square, decimal, lower-roman, upper-roman, lower-alpha, upper-alpha, none | list-style-type:upper-alpha | Y |\n| list-style-image |//url//, none | list-style-image:url(icFile.gif) | Y |\n| list-style-position |inside, outside | list-style-position:inside | Y |\n| list-style |//keyword// -or- //position// -or- //url// | list-style: square outside url(icFolder.gif) | Y |\n\n|>|>|>|>| !Positioning Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Applies Too'' | ''Inherited?'' |\n| clip |//shape//, auto | clip:rect(0px 200px 200px 0px) | all element | N |\n| height |//length//, auto | height:200px | DIV, SPAN and replaced element | N |\n| left |//length//, //percentage//, auto | left:0px | absolutely and relatively positioned element | N |\n| overflow |visible, hidden, scroll, auto | overflow:scroll | all element | N |\n| position |absolute, relative, static | position:absolute | all element | N |\n| top |//length//, //percentage//, auto | top:0px | absolutely and relatively positioned element | N |\n| visibility |visible, hidden, inherit | visibility:visible | all element | N |\n| width |//length//, //percentage//, auto | width:80%| DIV, SPAN and replaced element | N |\n| z-index |auto, //integer// | z-index:-1| absolutely and relatively positioned element | N |\n\n|>|>|>| !Printing Properties |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| page-break-before |auto, always -or- left, right | page-break-before:alway | N |\n| page-break-after |auto, always -or- left, right | page-break-before:auto | N |\n\n|>|>|>| !Pseudo Classes |\n| ''Property'' | ''Valid Values'' | ''Example'' | ''Inherited?'' |\n| cursor |auto, crosshair, default, hand, move, e-resize, ne-resize, nw-resize, n-resize, se-resize, sw-resize, s-resize, w-resize, text, wait, help | { cursor:hand; } | Y |\n| active, hover, link, visited | n/a | a:hover { color:red; } | Y |\n| first-letter, first-line |any font manipulating declaration | p:first-letter{ float:left;color:blue } | N |\n}}}}}}
/***\n| Name:|CloseOnCancelPlugin|\n| Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|\n| Version:|6.9.3|\n| Date:|30-Sep-2006|\n| Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\n***/\n//{{{\nmerge(config.commands.cancelTiddler,{\n\n handler_orig_closeUnsaved: config.commands.cancelTiddler.handler,\n\n handler: function(event,src,title) {\n this.handler_orig_closeUnsaved(event,src,title);\n if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))\n story.closeTiddler(title,true);\n return false;\n }\n\n});\n\n//}}}\n\n
Tag Cloud by Clint Checketts: [[http://15black.bluedepot.com/twtests/tagcloud.htm|http://15black.bluedepot.com/twtests/tagcloud.htm]]\n... done siglet style.\n\n<<tagCloud>>\n==:( unfortunately the popup context menus don't appear==\n==Still a few display glitches.==\nSeems to render OK in firefox, weird little bounding-box bug with Safari. No clue about IE (I care though... sort of... email me).
/***\n|''Name:''|CollapseTiddlersPlugin|\n|''Source:''|http://gensoft.revhost.net/Collapse.html|\n|''Author:''|Bradley Meck|\n|''License:''|unknown|\n|''~CoreVersion:''|2.0.10|\n\n|ELS 2/24/2006: added fallback to "CollapsedTemplate if "WebCollapsedTemplate" is not found |\n|ELS 2/6/2006: added check for 'readOnly' flag to use alternative "WebCollapsedTemplate" |\n\n***/\n\nconfig.commands.collapseTiddler = {\ntext: "fold",\ntooltip: "Collapse this tiddler",\nhandler: function(event,src,title)\n{\nvar e = story.findContainingTiddler(src);\nif(e.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){\nvar t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";\nif (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }\nif(e.getAttribute("template") != t ){\ne.setAttribute("oldTemplate",e.getAttribute("template"));\nstory.displayTiddler(null,title,t);\n}\n}\n}\n}\n\nconfig.commands.expandTiddler = {\ntext: "unfold",\ntooltip: "Expand this tiddler",\nhandler: function(event,src,title)\n{\nvar e = story.findContainingTiddler(src);\nstory.displayTiddler(null,title,e.getAttribute("oldTemplate"));\n}\n}\n\nconfig.macros.collapseAll = {\nhandler: function(place,macroName,params,wikifier,paramString,tiddler){\ncreateTiddlyButton(place,"Collapse All","",function(){\nstory.forEachTiddler(function(title,tiddler){\nif(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE])\nvar t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";\nif (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }\nstory.displayTiddler(null,title,t);\n})})\n}\n}\n\nconfig.macros.expandAll = {\nhandler: function(place,macroName,params,wikifier,paramString,tiddler){\ncreateTiddlyButton(place,"Expand All","",function(){\nstory.forEachTiddler(function(title,tiddler){\nvar t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";\nif (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }\nif(tiddler.getAttribute("template") == t) story.displayTiddler(null,title,tiddler.getAttribute("oldTemplate"));\n})})\n}\n}\n\nconfig.commands.collapseOthers = {\ntext: "focus",\ntooltip: "Expand this tiddler and collapse all others",\nhandler: function(event,src,title)\n{\nvar e = story.findContainingTiddler(src);\nstory.forEachTiddler(function(title,tiddler){\nif(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){\nvar t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";\nif (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }\nif (e==tiddler) t=e.getAttribute("oldTemplate");\n//////////\n// ELS 2006.02.22 - removed this line. if t==null, then the *current* view template, not the default "ViewTemplate", will be used.\n// if (!t||!t.length) t=!readOnly?"ViewTemplate":"WebViewTemplate";\n//////////\nstory.displayTiddler(null,title,t);\n}\n})\n}\n}
<!--{{{-->\n<div class='toolbar' macro='toolbar expandTiddler +collapseOthers -closeTiddler closeOthers editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<!--}}}-->\n
/%RGB hexadecimal 216-color "Web safe" palette %/\nSource: Paul Petterson, revised by Eric Shulman\n{{menubox{\n|bgcolor(#FFF):FFF |bgcolor(#CCC):CCC |bgcolor(#999):999 |bgcolor(#666):@@color(white):666@@ |bgcolor(#333):@@color(white):333@@ |bgcolor(#000):@@color(white):000@@ |bgcolor(#FC0):~FC0 |bgcolor(#F90):F90 |bgcolor(#F60):@@color(white):F60@@ |bgcolor(#F30):@@color(white):F30@@ |>|>|>|>|>| |\n|bgcolor(#9C0):9C0 |>|>|>| |bgcolor(#C90):C90 |bgcolor(#FC3):~FC3 |bgcolor(#FC6):~FC6 |bgcolor(#F96):F96 |bgcolor(#F63):@@color(white):F63@@ |bgcolor(#C30):@@color(white):C30@@ |>|>|>| |bgcolor(#C03):@@color(white):C03@@ |\n|bgcolor(#CF0):~CF0 |bgcolor(#CF3):~CF3 |bgcolor(#330):@@color(white):330@@ |bgcolor(#660):@@color(white):660@@ |bgcolor(#990):990 |bgcolor(#CC0):~CC0 |bgcolor(#FF0):~FF0 |bgcolor(#C93):C93 |bgcolor(#C63):@@color(white):C63@@ |bgcolor(#300):@@color(white):300@@ |bgcolor(#600):@@color(white):600@@ |bgcolor(#900):@@color(white):900@@ |bgcolor(#C00):@@color(white):C00@@ |bgcolor(#F00):@@color(white):F00@@ |bgcolor(#F36):@@color(white):F36@@ |bgcolor(#F03):@@color(white):F03@@ |\n|bgcolor(#9F0):9F0 |bgcolor(#CF6):~CF6 |bgcolor(#9C3):9C3 |bgcolor(#663):@@color(white):663@@ |bgcolor(#993):993 |bgcolor(#CC3):~CC3 |bgcolor(#FF3):~FF3 |bgcolor(#960):@@color(white):960@@ |bgcolor(#930):@@color(white):930@@ |bgcolor(#633):@@color(white):633@@ |bgcolor(#933):@@color(white):933@@ |bgcolor(#C33):@@color(white):C33@@ |bgcolor(#F33):@@color(white):F33@@ |bgcolor(#C36):@@color(white):C36@@ |bgcolor(#F69):@@color(white):F69@@ |bgcolor(#F06):@@color(white):F06@@ |\n|bgcolor(#6F0):6F0 |bgcolor(#9F6):9F6 |bgcolor(#6C3):6C3 |bgcolor(#690):690 |bgcolor(#996):996 |bgcolor(#CC6):~CC6 |bgcolor(#FF6):~FF6 |bgcolor(#963):@@color(white):963@@ |bgcolor(#630):@@color(white):630@@ |bgcolor(#966):@@color(white):966@@ |bgcolor(#C66):@@color(white):C66@@ |bgcolor(#F66):@@color(white):F66@@ |bgcolor(#903):@@color(white):903@@ |bgcolor(#C39):@@color(white):C39@@ |bgcolor(#F6C):@@color(white):~F6C@@ |bgcolor(#F09):@@color(white):F09@@ |\n|bgcolor(#3F0):3F0 |bgcolor(#6F3):6F3 |bgcolor(#390):390 |bgcolor(#6C0):6C0 |bgcolor(#9F3):9F3 |bgcolor(#CC9):~CC9 |bgcolor(#FF9):~FF9 |bgcolor(#C96):C96 |bgcolor(#C60):@@color(white):C60@@ |bgcolor(#C99):C99 |bgcolor(#F99):F99 |bgcolor(#F39):@@color(white):F39@@ |bgcolor(#C06):@@color(white):C06@@ |bgcolor(#906):@@color(white):906@@ |bgcolor(#F3C):@@color(white):~F3C@@ |bgcolor(#F0C):@@color(white):~F0C@@ |\n|bgcolor(#0C0):0C0 |bgcolor(#3C0):3C0 |bgcolor(#360):@@color(white):360@@ |bgcolor(#693):693 |bgcolor(#9C6):9C6 |bgcolor(#CF9):~CF9 |bgcolor(#FFC):FFC |bgcolor(#FC9):~FC9 |bgcolor(#F93):F93 |bgcolor(#FCC):FCC |bgcolor(#F9C):~F9C |bgcolor(#C69):@@color(white):C69@@ |bgcolor(#936):@@color(white):936@@ |bgcolor(#603):@@color(white):603@@ |bgcolor(#C09):@@color(white):C09@@ |bgcolor(#303):@@color(white):303@@ |\n|bgcolor(#3C3):3C3 |bgcolor(#6C6):6C6 |bgcolor(#0F0):0F0 |bgcolor(#3F3):3F3 |bgcolor(#6F6):6F6 |bgcolor(#9F9):9F9 |bgcolor(#CFC):CFC |>|>| |bgcolor(#C9C):~C9C |bgcolor(#969):@@color(white):969@@ |bgcolor(#939):@@color(white):939@@ |bgcolor(#909):@@color(white):909@@ |bgcolor(#636):@@color(white):636@@ |bgcolor(#606):@@color(white):606@@ |\n|bgcolor(#060):@@color(white):060@@ |bgcolor(#363):@@color(white):363@@ |bgcolor(#090):090 |bgcolor(#393):393 |bgcolor(#696):696 |bgcolor(#9C9):9C9 |>|>| |bgcolor(#FCF):FCF |bgcolor(#F9F):~F9F |bgcolor(#F6F):@@color(white):~F6F@@ |bgcolor(#F3F):@@color(white):~F3F@@ |bgcolor(#F0F):@@color(white):~F0F@@ |bgcolor(#C6C):@@color(white):~C6C@@ |bgcolor(#C3C):@@color(white):~C3C@@ |\n|bgcolor(#030):@@color(white):030@@ |bgcolor(#0C3):0C3 |bgcolor(#063):@@color(white):063@@ |bgcolor(#396):396 |bgcolor(#6C9):6C9 |bgcolor(#9FC):9FC |bgcolor(#CFF):CFF |bgcolor(#39F):39F |bgcolor(#9CF):9CF |bgcolor(#CCF):CCF |bgcolor(#C9F):~C9F |bgcolor(#96C):@@color(white):96C@@ |bgcolor(#639):@@color(white):639@@ |bgcolor(#306):@@color(white):306@@ |bgcolor(#90C):@@color(white):90C@@ |bgcolor(#C0C):@@color(white):~C0C@@ |\n|bgcolor(#0F3):0F3 |bgcolor(#3F6):3F6 |bgcolor(#093):093 |bgcolor(#0C6):0C6 |bgcolor(#3F9):3F9 |bgcolor(#9FF):9FF |bgcolor(#9CC):9CC |bgcolor(#06C):@@color(white):06C@@ |bgcolor(#69C):69C |bgcolor(#99F):99F |bgcolor(#99C):99C |bgcolor(#93F):@@color(white):93F@@ |bgcolor(#60C):@@color(white):60C@@ |bgcolor(#609):@@color(white):609@@ |bgcolor(#C3F):@@color(white):~C3F@@ |bgcolor(#C0F):@@color(white):~C0F@@ |\n|bgcolor(#0F6):0F6 |bgcolor(#6F9):6F9 |bgcolor(#3C6):3C6 |bgcolor(#096):096 |bgcolor(#6FF):6FF |bgcolor(#6CC):6CC |bgcolor(#699):699 |bgcolor(#036):@@color(white):036@@ |bgcolor(#369):@@color(white):369@@ |bgcolor(#66F):@@color(white):66F@@ |bgcolor(#66C):@@color(white):66C@@ |bgcolor(#669):@@color(white):669@@ |bgcolor(#309):@@color(white):309@@ |bgcolor(#93C):@@color(white):93C@@ |bgcolor(#C6F):@@color(white):~C6F@@ |bgcolor(#90F):@@color(white):90F@@ |\n|bgcolor(#0F9):0F9 |bgcolor(#6FC):6FC |bgcolor(#3C9):3C9 |bgcolor(#3FF):3FF |bgcolor(#3CC):3CC |bgcolor(#399):399 |bgcolor(#366):@@color(white):366@@ |bgcolor(#069):@@color(white):069@@ |bgcolor(#039):@@color(white):039@@ |bgcolor(#33F):@@color(white):33F@@ |bgcolor(#33C):@@color(white):33C@@ |bgcolor(#339):@@color(white):339@@ |bgcolor(#336):@@color(white):336@@ |bgcolor(#63C):@@color(white):63C@@ |bgcolor(#96F):@@color(white):96F@@ |bgcolor(#60F):@@color(white):60F@@ |\n|bgcolor(#0FC):0FC |bgcolor(#3FC):3FC |bgcolor(#0FF):0FF |bgcolor(#0CC):0CC |bgcolor(#099):099 |bgcolor(#066):@@color(white):066@@ |bgcolor(#033):@@color(white):033@@ |bgcolor(#39C):39C |bgcolor(#36C):@@color(white):36C@@ |bgcolor(#00F):@@color(white):00F@@ |bgcolor(#00C):@@color(white):00C@@ |bgcolor(#009):@@color(white):009@@ |bgcolor(#006):@@color(white):006@@ |bgcolor(#003):@@color(white):003@@ |bgcolor(#63F):@@color(white):63F@@ |bgcolor(#30F):@@color(white):30F@@ |\n|bgcolor(#0C9):0C9 |>|>|>| |bgcolor(#09C):09C |bgcolor(#3CF):3CF |bgcolor(#6CF):6CF |bgcolor(#69F):69F |bgcolor(#36F):@@color(white):36F@@ |bgcolor(#03C):@@color(white):03C@@ |>|>|>| |bgcolor(#30C):@@color(white):30C@@ |\n|>|>|>|>|>| |bgcolor(#0CF):0CF |bgcolor(#09F):09F |bgcolor(#06F):@@color(white):06F@@ |bgcolor(#03F):@@color(white):03F@@ |>|>|>|>|>| |\n<script>place.lastChild.style.width="95%"</script>}}}
/%comment%/+++[add a comment...]>\n <html><textarea id="comment" rows="10" style="width:100%"></textarea>\n <input type="button" value="submit comment" onclick="addTiddlerComment(this.previousSibling.previousSibling);"></html><script>\n place.lastChild.firstChild.value="Enter your comment text here";\n </script>\n===\n<script>\nwindow.addTiddlerComment = function(place) {\n if (!window.story) window.story=window; if (!store.getTiddler) store.getTiddler=function(title) {return this.tiddlers[title]}\n var title = story.findContainingTiddler(place).id.substr(7);\n var tiddler=store.getTiddler(title);\n var pos=tiddler.text.indexOf("/%"+place.id+"%/");\n if (pos==-1) pos=tiddler.text.length;\n var heading="comment from "+config.options.txtUserName+" on "+(new Date()).toLocaleString();\n var newtxt=tiddler.text.substr(0,pos);\n newtxt+="+++!!!!!["+heading+"]>\sn"+place.value+"===\sn";\n newtxt+=tiddler.text.substr(pos);\n store.saveTiddler(tiddler.title,tiddler.title,newtxt,tiddler.modifier,tiddler.modified,tiddler.tags);\n story.refreshTiddler(title,1,true);\n}\n</script>\n
//{{{\nconfig.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit\nconfig.options.chkInsertTabs = true; // tab inserts a tab when editing a tiddler\nconfig.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist\nconfig.views.editor.defaultText = ""; // don't need message when creating a new tiddler \n//}}}\n
/***\n|''Name:''|CopyTiddlerPlugin|\n|''Source:''|http://www.TiddlyTools.com/#CopyTiddlerPlugin|\n|''Author:''|TimMorgan|\n|''License:''|unknown|\n|''~CoreVersion:''|2.0.10|\n\nadds a "copy" option to duplicate a tiddler\n***/\n//{{{\nconfig.shadowTiddlers.EditTemplate = "<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler copyTiddler deleteTiddler'></div>\sn<div class='title' macro='view title'></div>\sn<div class='editor' macro='edit title'></div>\sn<div class='editor' macro='edit text'></div>\sn<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>";\n\nconfig.commands.copyTiddler = {\n text: 'copy',\n hideReadOnly: true,\n tooltip: 'Make a copy of this tiddler',\n handler: function(event,src,title) {\n story.displayTiddler(null,title,DEFAULT_VIEW_TEMPLATE);\n var tiddler = store.fetchTiddler(title);\n var newTitle = 'Copy of ' + title;\n var newTiddler = store.createTiddler(newTitle);\n newTiddler.text = tiddler.text;\n newTiddler.tags = tiddler.tags;\n story.displayTiddler(null,newTitle,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(newTitle,"title");\n return false;\n }\n};\n//}}}
{{{\n<<forEachTiddler\n write \n 'tiddler.title+"\sn"' \n\n toFile 'file:///c:/MyTiddlerList.txt' withLineSeparator '\sr\sn'\n>>\n}}}\n<<forEachTiddler\n write \n 'tiddler.title+"\sn"' \n\n toFile 'file:///c:/MyTiddlerList.txt' withLineSeparator '\sr\sn'\n>>\n\n
[[HOWTO Encrypt Your Home Directory Using CFS|http://gentoo-wiki.com/HOWTO_Encrypt_Your_Home_Directory_Using_CFS]]
[[Howto author AVI->DVD with menus using Linux only !|http://forums.gentoo.org/viewtopic.php?t=117709]]\n\n!Simple authoring with no menus\nTo create a more simple DVD with no menus or THX intro, then use the dvdauthor.xml config below:\nCode:\n{{{\n<dvdauthor dest="DVD">\n <vmgm />\n <titleset>\n <titles>\n <video widescreen="nopanscan" />\n <pgc>\n <vob file="matrix_dvd.mpg" chapters="0,0:30,1:00,1:30,2:30,3:00,3:30,4:00"/>\n </pgc>\n <pgc>\n <vob file="outtakes_dvd.mpg" chapters="0,0:30,1:00,1:30,2:30,3:00,3:30,4:00,4:30,5:00"/>\n </pgc>\n </titles>\n </titleset>\n</dvdauthor>\n}}}\nCreate a directory named 'DVD'.\nCreate the DVD file structure with:\n\nCode:\n{{{\ndvdauthor -x dvdauthor.xml\n}}}\n\nTest the new menus in xine before burning:\n\nCode:\n{{{\nxine dvd:/full/path/to/DVD/VIDEO_TS/\n}}}\nXine should play from the folder as though it's playing from a DVD.\n
Here are some examples that show the usage of tiddler data, as provided by the DataTiddlerPlugin.\n<<forEachTiddler\n where\n 'tiddler.tags.contains("DataTiddlerExample")'\n>>\n
/***\n|''Name:''|DataTiddlerPlugin|\n|''Version:''|1.0.6 (2006-08-26)|\n|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n!Description\nEnhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).\n\nSuch tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers. \n\n''//Example: "Table with all December Expenses"//''\n{{{\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\n}}}\n//(This assumes that expenses are stored in tiddlers tagged with "expense".)//\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\nFor other examples see DataTiddlerExamples.\n\n\n\n\n''Access and Modify Tiddler Data''\n\nYou can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields. \n\nThese values can be accessed and modified through the following Tiddler methods:\n|!Method|!Example|!Description|\n|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n\nAlternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.\n|!Method|!Description|\n|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n//(For details on the various functions see the detailed comments in the source code.)//\n\n\n''Data Representation in a Tiddler''\n\nThe data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]]. \n\n//''Data Section Example:''//\n{{{\n<data>{"isVIP":true,"user":"John Brown","age":34}</data>\n}}}\n\nThe data section is not displayed when viewing the tiddler (see also "The showData Macro").\n\nBeside the data section a tiddler may have all kind of other content.\n\nTypically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.\n\n\n''Saving Changes''\n\nThe "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.\n\n\n''Notifications''\n\nNo notifications are sent when a tiddler's data value is changed through the "setData" methods. \n\n''Escape Data Section''\nIn case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.\n\n\n''The showData Macro''\n\nBy default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:\n\n''Syntax:'' \n|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|\n|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|\n|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\n\n!Revision history\n* v1.0.6 (2006-08-26) \n** Removed misleading comment\n* v1.0.5 (2006-02-27) (Internal Release Only)\n** Internal\n*** Make "JSLint" conform\n* v1.0.4 (2006-02-05)\n** Bugfix: showData fails in TiddlyWiki 2.0\n* v1.0.3 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.2 (2005-12-22)\n** Enhancements:\n*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.\n*** Improved (JSON) error messages.\n** Bugs fixed: \n*** References are not updated when using the DataTiddler.\n*** Changes to compound objects are not always saved.\n*** "~</data>" is not rendered correctly (expected "</data>")\n* v1.0.1 (2005-12-13)\n** Features: \n*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed\n** Bugs fixed: \n*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)\n* v1.0.0 (2005-12-12)\n** initial version\n\n!Code\n***/\n//{{{\n//============================================================================\n//============================================================================\n// DataTiddlerPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the DataTiddler Plugin is only installed once.\n//\nif (!version.extensions.DataTiddlerPlugin) {\n\n\n\nversion.extensions.DataTiddlerPlugin = {\n major: 1, minor: 0, revision: 6,\n date: new Date(2006, 7, 26), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"\n};\n\n// For backward compatibility with v1.2.x\n//\nif (!window.story) window.story=window; \nif (!TiddlyWiki.prototype.getTiddler) {\n TiddlyWiki.prototype.getTiddler = function(title) { \n var t = this.tiddlers[title]; \n return (t !== undefined && t instanceof Tiddler) ? t : null; \n };\n}\n\n//============================================================================\n// DataTiddler Class\n//============================================================================\n\n// ---------------------------------------------------------------------------\n// Configurations and constants \n// ---------------------------------------------------------------------------\n\nfunction DataTiddler() {\n}\n\nDataTiddler = {\n // Function to stringify a JavaScript value, producing the text for the data section content.\n // (Must match the implementation of DataTiddler.parse.)\n //\n stringify : null,\n \n\n // Function to parse the text for the data section content, producing a JavaScript value.\n // (Must match the implementation of DataTiddler.stringify.)\n //\n parse : null\n};\n\n// Ensure access for IE\nwindow.DataTiddler = DataTiddler;\n\n// ---------------------------------------------------------------------------\n// Data Accessor and Mutator\n// ---------------------------------------------------------------------------\n\n\n// Returns the value of the given data field of the tiddler.\n// When no such field is defined or its value is undefined\n// the defaultValue is returned.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.getData = function(tiddler, field, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataValue(t, field, defaultValue);\n};\n\n\n// Sets the value of the given data field of the tiddler to\n// the value. When the value is equal to the defaultValue\n// no value is set (and the field is removed)\n//\n// Changing data of a tiddler will not trigger notifications.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.setData = function(tiddler, field, value, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler+ "("+t+")";\n }\n\n DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);\n};\n\n\n// Returns the data object of the tiddler, with a property for every field.\n//\n// The properties of the returned data object may only be read and\n// not be modified. To modify the data use DataTiddler.setData(...) \n// or the corresponding Tiddler method.\n//\n// If no data section is defined a new (empty) object is returned.\n//\n// @param tiddler either a tiddler name or a Tiddler\n//\nDataTiddler.getDataObject = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataObject(t);\n};\n\n// Returns the text of the content of the data section of the tiddler.\n//\n// When no data section is defined for the tiddler null is returned \n//\n// @param tiddler either a tiddler name or a Tiddler\n// @return [may be null]\n//\nDataTiddler.getDataText = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.readDataSectionText(t);\n};\n\n\n// ---------------------------------------------------------------------------\n// Internal helper methods (must not be used by code from outside this plugin)\n// ---------------------------------------------------------------------------\n\n// Internal.\n//\n// The original JSONError is not very user friendly, \n// especially it does not define a toString() method\n// Therefore we extend it here.\n//\nDataTiddler.extendJSONError = function(ex) {\n if (ex.name == 'JSONError') {\n ex.toString = function() {\n return ex.name + ": "+ex.message+" ("+ex.text+")";\n };\n }\n return ex;\n};\n\n// Internal.\n//\n// @param t a Tiddler\n//\nDataTiddler.getTiddlerDataObject = function(t) {\n if (t.dataObject === undefined) {\n var data = DataTiddler.readData(t);\n t.dataObject = (data) ? data : {};\n }\n \n return t.dataObject;\n};\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {\n var value = DataTiddler.getTiddlerDataObject(tiddler)[field];\n return (value === undefined) ? defaultValue : value;\n};\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n var oldValue = data[field];\n \n if (value == defaultValue) {\n if (oldValue !== undefined) {\n delete data[field];\n DataTiddler.save(tiddler);\n }\n return;\n }\n data[field] = value;\n DataTiddler.save(tiddler);\n};\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns its text\n// (as a String).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readDataSectionText = function(tiddler) {\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n if (matches === null || !matches[2]) {\n return null;\n }\n return matches[2];\n};\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns it\n// (as an internalized object).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readData = function(tiddler) {\n var text = DataTiddler.readDataSectionText(tiddler);\n try {\n return text ? DataTiddler.parse(text) : null;\n } catch(ex) {\n throw DataTiddler.extendJSONError(ex);\n }\n};\n\n// Internal.\n// \n// Returns the serialized text of the data of the given tiddler, as it\n// should be stored in the data section.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getDataTextOfTiddler = function(tiddler) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n return DataTiddler.stringify(data);\n};\n\n\n// Internal.\n// \nDataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {\n var index = s.indexOf(subString, startIndex);\n while ((index > 0) && (s[index-1] == '~')) { \n index = s.indexOf(subString, index+1);\n }\n return index;\n};\n\n// Internal.\n//\nDataTiddler.getDataSectionInfo = function(text) {\n // Special care must be taken to handle "<data>" and "</data>" texts inside\n // a data section. \n // Also take care not to use an escaped <data> (i.e. "~<data>") as the start \n // of a data section. (Same for </data>)\n\n // NOTE: we are explicitly searching for a data section that contains a JSON\n // string, i.e. framed with braces. This way we are little bit more robust in\n // case the tiddler contains unescaped texts "<data>" or "</data>". This must\n // be changed when using a different stringifier.\n\n var startTagText = "<data>{";\n var endTagText = "}</data>";\n\n var startPos = 0;\n\n // Find the first not escaped "<data>".\n var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);\n if (startDataTagIndex < 0) {\n return null;\n }\n\n // Find the *last* not escaped "</data>".\n var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);\n if (endDataTagIndex < 0) {\n return null;\n }\n var nextEndDataTagIndex;\n while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {\n endDataTagIndex = nextEndDataTagIndex;\n }\n\n return {\n prefixEnd: startDataTagIndex, \n dataStart: startDataTagIndex+(startTagText.length)-1, \n dataEnd: endDataTagIndex, \n suffixStart: endDataTagIndex+(endTagText.length)\n };\n};\n\n// Internal.\n// \n// Returns the "matches" of a content of a DataTiddler on the\n// "data" regular expression. Return null when no data is defined\n// in the tiddler content.\n//\n// Group 1: text before data section (prefix)\n// Group 2: content of data section\n// Group 3: text behind data section (suffix)\n//\n// @param tiddler a Tiddler\n// @return [may be null] null when the tiddler contains no data section, otherwise see above.\n//\nDataTiddler.getDataTiddlerMatches = function(tiddler) {\n var text = tiddler.text;\n var info = DataTiddler.getDataSectionInfo(text);\n if (!info) {\n return null;\n }\n\n var prefix = text.substr(0,info.prefixEnd);\n var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);\n var suffix = text.substr(info.suffixStart);\n \n return [text, prefix, data, suffix];\n};\n\n\n// Internal.\n//\n// Saves the data in a <data> block of the given tiddler (as a minor change). \n//\n// The "chkAutoSave" and "chkForceMinorUpdate" options are respected. \n// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.\n//\n// Notifications are not send. \n//\n// This method should only be called when the data really has changed. \n//\n// @param tiddler\n// the tiddler to be saved.\n//\nDataTiddler.save = function(tiddler) {\n\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n\n var prefix;\n var suffix;\n if (matches === null) {\n prefix = tiddler.text;\n suffix = "";\n } else {\n prefix = matches[1];\n suffix = matches[3];\n }\n\n var dataText = DataTiddler.getDataTextOfTiddler(tiddler);\n var newText = \n (dataText !== null) \n ? prefix + "<data>" + dataText + "</data>" + suffix\n : prefix + suffix;\n if (newText != tiddler.text) {\n // make the change in the tiddlers text\n \n // ... see DataTiddler.MyTiddlerChangedFunction\n tiddler.isDataTiddlerChange = true;\n \n // ... do the action change\n tiddler.set(\n tiddler.title,\n newText,\n config.options.txtUserName, \n config.options.chkForceMinorUpdate? undefined : new Date(),\n tiddler.tags);\n\n // ... see DataTiddler.MyTiddlerChangedFunction\n delete tiddler.isDataTiddlerChange;\n\n // Mark the store as dirty.\n store.dirty = true;\n \n // AutoSave if option is selected\n if(config.options.chkAutoSave) {\n saveChanges();\n }\n }\n};\n\n// Internal.\n//\nDataTiddler.MyTiddlerChangedFunction = function() {\n // Remove the data object from the tiddler when the tiddler is changed\n // by code other than DataTiddler code. \n //\n // This is necessary since the data object is just a "cached version" \n // of the data defined in the data section of the tiddler and the \n // "external" change may have changed the content of the data section.\n // Thus we are not sure if the data object reflects the data section \n // contents. \n // \n // By deleting the data object we ensure that the data object is \n // reconstructed the next time it is needed, with the data defined by\n // the data section in the tiddler's text.\n \n // To indicate that a change is a "DataTiddler change" a temporary\n // property "isDataTiddlerChange" is added to the tiddler.\n if (this.dataObject && !this.isDataTiddlerChange) {\n delete this.dataObject;\n }\n \n // call the original code.\n DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);\n};\n\n\n//============================================================================\n// Formatters\n//============================================================================\n\n// This formatter ensures that "~<data>" is rendered as "<data>". This is used to \n// escape the "<data>" of a data section, just in case someone really wants to use\n// "<data>" as a text in a tiddler and not start a data section.\n//\n// Same for </data>.\n//\nconfig.formatters.push( {\n name: "data-escape",\n match: "~<\s\s/?data>",\n\n handler: function(w) {\n w.outputText(w.output,w.matchStart + 1,w.nextMatch);\n }\n} );\n\n\n// This formatter ensures that <data>...</data> sections are not rendered.\n//\nconfig.formatters.push( {\n name: "data",\n match: "<data>",\n\n handler: function(w) {\n var info = DataTiddler.getDataSectionInfo(w.source);\n if (info && info.prefixEnd == w.matchStart) {\n w.nextMatch = info.suffixStart;\n } else {\n w.outputText(w.output,w.matchStart,w.nextMatch);\n }\n }\n} );\n\n\n//============================================================================\n// Tiddler Class Extension\n//============================================================================\n\n// "Hijack" the changed method ---------------------------------------------------\n\nDataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;\nTiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;\n\n// Define accessor methods -------------------------------------------------------\n\n// Returns the value of the given data field of the tiddler. When no such field \n// is defined or its value is undefined the defaultValue is returned.\n//\n// When field is undefined (or null) the data object is returned. (See \n// DataTiddler.getDataObject.)\n//\n// @param field [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n// @return [may be null, undefined]\n//\nTiddler.prototype.data = function(field, defaultValue) {\n return (field) \n ? DataTiddler.getTiddlerDataValue(this, field, defaultValue)\n : DataTiddler.getTiddlerDataObject(this);\n};\n\n// Sets the value of the given data field of the tiddler to the value. When the \n// value is equal to the defaultValue no value is set (and the field is removed).\n//\n// @param value [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n//\nTiddler.prototype.setData = function(field, value, defaultValue) {\n DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);\n};\n\n\n//============================================================================\n// showData Macro\n//============================================================================\n\nconfig.macros.showData = {\n // Standard Properties\n label: "showData",\n prompt: "Display the values stored in the data section of the tiddler"\n};\n\nconfig.macros.showData.handler = function(place,macroName,params) {\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n // Parse the optional "JSON"\n var showInJSONFormat = false;\n if ((i < params.length) && params[i] == "JSON") {\n i++;\n showInJSONFormat = true;\n }\n \n var tiddlerName = story.findContainingTiddler(place).id.substr(7);\n if (i < params.length) {\n tiddlerName = params[i];\n i++;\n }\n\n // --- Processing ------------------------------------------\n try {\n if (showInJSONFormat) {\n this.renderDataInJSONFormat(place, tiddlerName);\n } else {\n this.renderDataAsTable(place, tiddlerName);\n }\n } catch (e) {\n this.createErrorElement(place, e);\n }\n};\n\nconfig.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {\n var text = DataTiddler.getDataText(tiddlerName);\n if (text) {\n createTiddlyElement(place,"pre",null,null,text);\n }\n};\n\nconfig.macros.showData.renderDataAsTable = function(place,tiddlerName) {\n var text = "|!Name|!Value|\sn";\n var data = DataTiddler.getDataObject(tiddlerName);\n if (data) {\n for (var i in data) {\n var value = data[i];\n text += "|"+i+"|"+DataTiddler.stringify(value)+"|\sn";\n }\n }\n \n wikify(text, place);\n};\n\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.showData.createErrorElement = function(place, exception) {\n var message = (exception.description) ? exception.description : exception.toString();\n return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);\n};\n\n// ---------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// ---------------------------------------------------------------------------\n//\nsetStylesheet(\n ".showDataError{color: #ffffff;background-color: #880000;}",\n "showData");\n\n\n} // of "install only once"\n// Used Globals (for JSLint) ==============\n\n// ... TiddlyWiki Core\n/*global createTiddlyElement, saveChanges, store, story, wikify */\n// ... DataTiddler\n/*global DataTiddler */\n// ... JSON\n/*global JSON */\n \n\n/***\n!JSON Code, used to serialize the data\n***/\n/*\nCopyright (c) 2005 JSON.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe Software shall be used for Good, not Evil.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n/*\n The global object JSON contains two methods.\n\n JSON.stringify(value) takes a JavaScript value and produces a JSON text.\n The value must not be cyclical.\n\n JSON.parse(text) takes a JSON text and produces a JavaScript value. It will\n throw a 'JSONError' exception if there is an error.\n*/\nvar JSON = {\n copyright: '(c)2005 JSON.org',\n license: 'http://www.crockford.com/JSON/license.html',\n/*\n Stringify a JavaScript value, producing a JSON text.\n*/\n stringify: function (v) {\n var a = [];\n\n/*\n Emit a string.\n*/\n function e(s) {\n a[a.length] = s;\n }\n\n/*\n Convert a value.\n*/\n function g(x) {\n var c, i, l, v;\n\n switch (typeof x) {\n case 'object':\n if (x) {\n if (x instanceof Array) {\n e('[');\n l = a.length;\n for (i = 0; i < x.length; i += 1) {\n v = x[i];\n if (typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(v);\n }\n }\n e(']');\n return;\n } else if (typeof x.toString != 'undefined') {\n e('{');\n l = a.length;\n for (i in x) {\n v = x[i];\n if (x.hasOwnProperty(i) &&\n typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(i);\n e(':');\n g(v);\n }\n }\n return e('}');\n }\n }\n e('null');\n return;\n case 'number':\n e(isFinite(x) ? +x : 'null');\n return;\n case 'string':\n l = x.length;\n e('"');\n for (i = 0; i < l; i += 1) {\n c = x.charAt(i);\n if (c >= ' ') {\n if (c == '\s\s' || c == '"') {\n e('\s\s');\n }\n e(c);\n } else {\n switch (c) {\n case '\sb':\n e('\s\sb');\n break;\n case '\sf':\n e('\s\sf');\n break;\n case '\sn':\n e('\s\sn');\n break;\n case '\sr':\n e('\s\sr');\n break;\n case '\st':\n e('\s\st');\n break;\n default:\n c = c.charCodeAt();\n e('\s\su00' + Math.floor(c / 16).toString(16) +\n (c % 16).toString(16));\n }\n }\n }\n e('"');\n return;\n case 'boolean':\n e(String(x));\n return;\n default:\n e('null');\n return;\n }\n }\n g(v);\n return a.join('');\n },\n/*\n Parse a JSON text, producing a JavaScript value.\n*/\n parse: function (text) {\n var p = /^\ss*(([,:{}\s[\s]])|"(\s\s.|[^\sx00-\sx1f"\s\s])*"|-?\sd+(\s.\sd*)?([eE][+-]?\sd+)?|true|false|null)\ss*/,\n token,\n operator;\n\n function error(m, t) {\n throw {\n name: 'JSONError',\n message: m,\n text: t || operator || token\n };\n }\n\n function next(b) {\n if (b && b != operator) {\n error("Expected '" + b + "'");\n }\n if (text) {\n var t = p.exec(text);\n if (t) {\n if (t[2]) {\n token = null;\n operator = t[2];\n } else {\n operator = null;\n try {\n token = eval(t[1]);\n } catch (e) {\n error("Bad token", t[1]);\n }\n }\n text = text.substring(t[0].length);\n } else {\n error("Unrecognized token", text);\n }\n } else {\n token = operator = undefined;\n }\n }\n\n\n function val() {\n var k, o;\n switch (operator) {\n case '{':\n next('{');\n o = {};\n if (operator != '}') {\n for (;;) {\n if (operator || typeof token != 'string') {\n error("Missing key");\n }\n k = token;\n next();\n next(':');\n o[k] = val();\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next('}');\n return o;\n case '[':\n next('[');\n o = [];\n if (operator != ']') {\n for (;;) {\n o.push(val());\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next(']');\n return o;\n default:\n if (operator !== null) {\n error("Missing value");\n }\n k = token;\n next();\n return k;\n }\n }\n next();\n return val();\n }\n};\n\n/***\n!Setup the data serialization\n***/\n\nDataTiddler.format = "JSON";\nDataTiddler.stringify = JSON.stringify;\nDataTiddler.parse = JSON.parse;\n\n//}}}\n\n
!SQLite -> MySQL\n\nAn (unsupported) way to transfer your SQLite3 database to MySQL:\n{{{\n cd ~/.kde/share/apps/amarok && \s\n sqlite3 collection.db .dump | \s \n grep -v "BEGIN TRANSACTION;" | \s\n grep -v "COMMIT;" | \s\n perl -pe 's/INSERT INTO \s"(.*)\s" VALUES/INSERT INTO \s1 VALUES/' | \n mysql -u root -p amarok\n}}}\nSome had trouble with the previous script that was here, but the above version worked. If you get an error, (album names with backslashes can cause problems) then drop the last line above and output the results to a file. \n{{{\n cd ......\s1 VALUES/' > ~/tmp/amarok_dump\n}}}\nEdit the file to fix the errors in whatever handy text editor you prefer. Delete any tables that were created in the Amarok database (I used phpMyAdmin, but if you want to do this via MySQL commands and don't know how... seek information in [http://dev.mysql.com/doc/refman/5.0/en/ the MySQL Reference Manual]). Then try the last part again using your output file.\n{{{\n cat ~/tmp/amarok_dump | mysql -u root -p amarok\n}}}\nThe original script tried to commit the following substitution: s/VARCHAR\s(256\s)/VARCHAR\s(255\s)/\nhowever my SQLite dump file only had VARCHAR(255) references. You might want to check yours to make sure by running something like:\n{{{\n grep "VARCHAR(256)" ~/tmp/amarok_dump\n}}}\nIf you get any results then try to fix them with:\n{{{\n perl -pe 's/VARCHAR\s(256\s)/VARCHAR\s(255\s)/' < ~/tmp/amarok_dump > ~/tmp/amarok_dump2 && mv ~/tmp/amarok_dump2 ~/tmp/amarok_dump\n}}}\nMySQL also comes by default with a useful command line utility called replace, which can replace multiple strings within a file:\n {{{\n replace "VARCHAR(256)" "VARCHAR(255)" -- ~/tmp/amarok_dump\n}}}\nYou can also specify several pairs of strings for the search/replace provided you remember to terminate the line with:\n{{{\n -- ~/tmp/amarok_dump\n}}}\nAn alternate method is to import my SQLite data as follows:\n* Start Amarok, change to MySQL, and build the database (but don't play any songs)\n* Download [http://sourceforge.net/projects/sqlitebrowser/ SQLite Database Browser]\n* Export the statistics database to a dump file, amarok_dump.sql\n* Remove all BEGIN TRANSACTION, COMMIT and CREATE sql commands\n* Import the file using MySQL:\n{{{\n cat amarok_dump.sql | mysql -u root -p amarok\n}}}\nIf you receive any errors, its possible that you played some songs and a statistics entry already exists for a particular file. If this is the case, you will have to edit amarok_dump.sql, find the offending line and remove EVERYTHING before it (since those commands have already been executed by MySQL - you will get errors otherwise). If you want to still use the offending line, replace INSERT INTO with REPLACE INTO. Re run the above command.\n\n!MySQL -> SQLite\n\nAn (unsupported) way to transfer your MySQL database to SQLite3:\n\n('''Note this will not currently work with Amarok >= 1.4.2 due to changes in the schema''')\n{{{\n cd ~/.kde/share/apps/amarok && \s\n mv collection.db collection.db.old && \s\n mysqldump -uroot -p -n -t amarok | sed -e "s/\s\s\s'/\s'\s'/g" | sed -e "s/\s\s\s\s\s"/\s"\s"/g" > amarok.sql && \s\n sqlite3 collection.db\n}}}\npaste to your "sqlite>" prompt to create the tables:\n{{{\n CREATE TABLE album (id INTEGER PRIMARY KEY ,name VARCHAR(255) );\n CREATE TABLE artist (id INTEGER PRIMARY KEY ,name VARCHAR(255) );\n CREATE TABLE directories (dir VARCHAR(255) UNIQUE,changedate INTEGER );\n CREATE TABLE genre (id INTEGER PRIMARY KEY ,name VARCHAR(255) );\n CREATE TABLE images (path VARCHAR(255),artist VARCHAR(255),album VARCHAR(255) );\n CREATE TABLE related_artists (artist VARCHAR(255),suggestion VARCHAR(255),changedate INTEGER );\n CREATE TABLE statistics (url VARCHAR(255) UNIQUE,createdate INTEGER,accessdate INTEGER,percentage FLOAT,playcounter INTEGER,rating INTEGER);\n CREATE TABLE tags (url VARCHAR(255),dir VARCHAR(255),createdate INTEGER,album INTEGER,artist INTEGER,genre INTEGER,title VARCHAR(255),year INTEGER,comment VARCHAR(255),track NUMERIC(4),bitrate INTEGER,length INTEGER,samplerate INTEGER,sampler BOOL );\n CREATE TABLE year (id INTEGER PRIMARY KEY ,name VARCHAR(4) );\n CREATE INDEX album_idx ON album( name );\n CREATE INDEX album_tag ON tags( album );\n CREATE INDEX artist_idx ON artist( name );\n CREATE INDEX artist_tag ON tags( artist );\n CREATE INDEX directories_dir ON directories( dir );\n CREATE INDEX genre_idx ON genre( name );\n CREATE INDEX genre_tag ON tags( genre );\n CREATE INDEX images_album ON images( album );\n CREATE INDEX images_artist ON images( artist );\n CREATE INDEX percentage_stats ON statistics( percentage );\n CREATE INDEX playcounter_stats ON statistics( playcounter );\n CREATE INDEX related_artists_artist ON related_artists( artist );\n CREATE INDEX sampler_tag ON tags( sampler );\n CREATE INDEX url_stats ON statistics( url );\n CREATE INDEX url_tag ON tags( url );\n CREATE INDEX year_idx ON year( name );\n CREATE INDEX year_tag ON tags( year );\n}}}\nand import your mysqldump at your "sqlite>" prompt:\n{{{\n .read amarok.sql\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
[[Journal]] ReferenceGuide CloudWrapper
Double click on this entry. This will bring you into Editing Mode. Type whatever you want to in the large text box, then move your mouse next to the title of this tiddler and click "done".\n\nIsn't that cool?\n\nNow, if you want to know HowToSaveYourChanges, you'll have to save the TiddlyWiki to your hard drive. Find out how in EasyToCarry.\n\nYou can also learn \n*HowToMakeATiddler\n*HowToFormatText\n*HowToEmbedImages\n*HowToMakeLists\n*HowToMakeTables\n*HowToCreateSubheadings.\n*HowToUseBlockquotes\n*HowToAddAHorizontalLine\n*HowToDewikifyAWikiWord\n*[[HowToAddMonospacedText|MonospacedText]]\n*HowToMakeExternalLinks\n*[[HowToTagATiddler|Tags]]\n*[[HowToAddAMacro|Macros]]\n*[[HowToChangeAMenuOrTheSiteTitle|SpecialTiddlers]]\n*HowToFormatThePage
[[MptwEditTemplate]]\n
/***\n<<tiddler EncryptionPluginDocumentation>>\n!Code\n***/\n//{{{\nversion.extensions.EncryptionPlugin = { major: 1, minor: 0, revision: 1, date: new Date(2006,18,3),\n source: "http://yann.perrin.googlepages.com/twkd.html#EncryptionPlugin"\n};\n//}}}\n/***\n// // Encrypt Command Definition\n***/\n//{{{\nconfig.macros.encrypt = {\n label: '§',\n tooltip: 'Encrypt this tiddler',\n getkeydialog: 'Enter encryption key',\n cryptedtag: 'crypted',\n donotcrypttag: 'EncryptionPlugin'\n};\nconfig.macros.encrypt.action = function(tiddler) {\n var key = prompt(this.getkeydialog,'');\n if (key)\n {\n tiddler.text = TEAencrypt(tiddler.text,key);\n tiddler.tags.push(this.cryptedtag);\n if (version.major < 2)\n store.tiddlers[tiddler.title] = tiddler;\n else\n store.addTiddler(tiddler);\n story.refreshTiddler(tiddler.title,1,true);\n store.notifyAll();\n }\n};\nconfig.macros.encrypt.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nif (tiddler.tags.find(this.cryptedtag)==null && tiddler.tags.find(this.donotcrypttag)==null)\ncreateTiddlyButton(place, this.label, this.tooltip, function () {config.macros.encrypt.action(tiddler); return false;}, null, null, null);\n}\n//}}}\n// // Decrypt Command Definition\n//{{{\nconfig.macros.decrypt = {\n label: '-§-',\n tooltip: 'Decrypt this tiddler',\n cryptedtag:'crypted',\n donotdecrypttag:'EncryptionPlugin',\n getkeydialog: 'Enter encryption key'\n};\nconfig.macros.decrypt.action = function(tiddler) {\n var key = prompt(this.getkeydialog,'');\n if (key)\n {\n tiddler.text = TEAdecrypt(tiddler.text,key);\n tiddler.tags.splice(tiddler.tags.find(this.cryptedtag),1);\n if (version.major < 2)\n store.tiddlers[tiddler.title] = tiddler;\n else\n store.addTiddler(tiddler);\n story.refreshTiddler(tiddler.title,1,true);\n store.notifyAll();\n }\n};\nconfig.macros.decrypt.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nif (tiddler.tags.find(this.cryptedtag)!=null && tiddler.tags.find(this.donotdecrypttag)==null)\ncreateTiddlyButton(place, this.label, this.tooltip, function () {config.macros.decrypt.action(tiddler); return false;}, null, null, null);\n}\n//}}}\n// //Shadow tiddlers definition\n//{{{\nconfig.shadowTiddlers.ViewTemplate="<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'><span macro='encrypt'></span><span macro='decrypt'></span></div>\sn<div class='title' macro='view title'></div>\sn<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>)</div>\sn<div class='tagging' macro='tagging'></div>\sn<div class='tagged' macro='tags'></div>\sn<div class='viewer' macro='view text wikified'></div>\sn<div class='tagClear'></div>";\nconfig.shadowTiddlers.EncryptionPluginDocumentation="Documentation for this plugin is available [[here|" + version.extensions.EncryptionPlugin.source +"Documentation]]";\n//}}}
|Name|EncryptionPlugin|\n|Author|YannPerrin|\n|Location|http://yann.perrin.googlepages.com/twkd.html#EncryptionPlugin|\n|Version|1.0.1|\n|Requires|~TW2.x|\n\n!Description\nThis plugin allow you to encrypt and decrypt individual tiddlers.\n\n!Installation\n*import (or copy/paste in edit mode) the following tiddlers into your document:<<br>>EncryptionPlugin<<br>>[[TEA]] (tag them with systemConfig)\n*if you want to have offline access to this plugin documentation, import (or copy/paste in edit mode) the following tiddlers into your document:<<br>>EncryptionPluginDocumentation\n*if your ViewTemplate isn't a ShadowTiddler anymore, you will have to add\n{{{\n<span macro='encrypt'></span><span macro='decrypt'></span>\n}}}\ninside the 'toolbar' div\n\n!Usage\n''Once properly installed'' (see above), this plugin should add a '§' command to the toolbar. Clicking on it will ask for a key and then trigger the tiddler encryption.\nCrypted tiddler will have the '-§-' command instead. It will trigger tiddler decryption once clicked.\n''an invalid decription key will destroy your tiddler data, so be carefull !''\n\n!Revision History\n2006.18.03-1.0.1\n>added empty key detection\n2006.18.03-1.0.0\n>Initial release\n
TiddlyWiki is being used for all kinds of things:\n* Schools in South Australia to [[distribute class materials to students|https://secure.ait.org/wiki/background.htm]]\n* ChrisJohnson's [[personal home page|http://www.spkml.com/]]\n* JacksonBoyle's collection of [[recipes|http://jacksonboyle.com/kitchen.htm]]\n* JonathanCamp's guide to [[Prince 2 project management|http://www.microupdate.net/cms/doc/PrinceII.html]]\n* BrandonSiegel's [[Case Personal Security Device Project|http://anubis.case.edu/398n]]\n* MichaelDansie's site for the [[American Cryptogram Association|http://msig.med.utah.edu/RunningUtes/cryptogram/aca.html]]\n* BrianHolland's [[student nodes|http://www.acsu.buffalo.edu/~bholland/]] from Buffalo Law School\n* RuiCarmo's [[Python Grimoire|http://the.taoofmac.com/space/Python/Grimoire]], a sort of recipe book for the programming language Python\n* Rich Kulesus' [[themer's blog|http://www.skinyourscreen.com/mrbiotech/]]\n* Qliner Software are using TiddlyWiki to create the site for their [[hotkeys|http://www.qliner.com/hotkeys/]] product\n* AndreasKänner's family home page at http://www.kaenner.de/\n* EliseSpringer, a philospher at Wesleyan University in Connecticut, USA, is using TiddlyWiki for her homepage at http://espringer.web.wesleyan.edu/ and for [[ReasoningWell|http://parmenides.objectis.net/reason/]], a wiki for her Philosophy faculty\n* MarkWygent of Wygent Reeds, a maker of Scottish bagpipe reeds from Delaware, has compiled a fascinating home page using TiddlyWiki at http://www.wygent.com/\n* ChristopherJames has compiled a comprehensive guide to TabletPCs at http://www.tabletpcwiki.net/\n* MiguelCentellas has created an extensive guide to Bolivian politics at http://www.centellas.org/politics/politiddly.html\n* BrunoTiagoRodrigues has created a geocaching community site in Portuguese at http://travelbugrace.geocaching-pt.net/.\n* CharlesStross, a celebrated British ScienceFiction writer, has used TiddlyWiki for his 'Tough Guide to the Rapture of the Nerds' at http://www.antipope.org/charlie/toughguide.html.\n* KristofferNilausOlsen, a member of the Danish Student Group of Amnesty International, has used TiddlyWiki to collate reports of breaches of human rights. His site is at http://www.resultat.dk/sg/tw/students.html.\n* MartinSilcock, an brand researcher working with Millward Brown, is using TiddlyWiki for his homepage at http://www.explorate.co.uk/.\n* Many people are using the GTDTiddlyWiki variant for personal productivity, and there's been some interesting experiments in TiddlyWikiFiction.\n
The following macro call exports all tiddlers to a text file "c:/MyTiddlyWikiExport.txt", using a customized format.\n{{{\n<<forEachTiddler\n script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "==== "+tiddler.title+"=========================\snTags: "+ getSortedTagsText(tiddler)+"\snModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\snModifier: "+tiddler.modifier+"\sn--------------------------------------------------\sn"+tiddler.text+"\sn--------------------------------------------------\sn(End of "+tiddler.title+")\sn\sn\sn\sn"}'\n write \n 'writeTiddler(tiddler)' \n toFile 'file:///c:/MyTiddlyWikiExport.txt' withLineSeparator '\sr\sn'\n>>\n}}}\nFor better readablility here the script text in a nicer layout:\n{{{\nfunction getSortedTagsText(tiddler) {\n var tags = tiddler.tags; \n if (!tags) \n return ""; \n tags.sort(); \n var result = ""; \n for (var i = 0; i < tags.length;i++) {\n result += tags[i]+ " ";\n } \n return result;\n} \n\nfunction writeTiddler(tiddler) {\n return "==== "+tiddler.title+"=========================\sn"+\n "Tags: "+ getSortedTagsText(tiddler)+"\sn"+\n "Modified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\sn"+\n "Modifier: "+tiddler.modifier+"\sn"+\n "--------------------------------------------------\sn"+\n tiddler.text+"\sn"+\n "--------------------------------------------------\sn"\n "(End of "+tiddler.title+")\sn\sn\sn\sn"\n}\n}}}\n\n<<forEachTiddler\n script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "==== "+tiddler.title+"=========================\snTags: "+ getSortedTagsText(tiddler)+"\snModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\snModifier: "+tiddler.modifier+"\sn--------------------------------------------------\sn"+tiddler.text+"\sn--------------------------------------------------\sn(End of "+tiddler.title+")\sn\sn\sn\sn"}'\n write \n 'writeTiddler(tiddler)' \n toFile 'file:///c:/MyTiddlyWikiExport.txt' withLineSeparator '\sr\sn'\n>>\n\n
<<exportTiddlers inline>>
/***\n|''Name:''|ExportTiddlersPlugin|\n|''Source:''|http://www.TiddlyTools.com/#ExportTiddlersPlugin|\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 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 (used in XML export)\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* SiteNotify^^\naddresses (if any) for sending automatic server-side email notices\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.10.12 [2.2.3]'' in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format. Based on report from Jose Gonzalez.\n''2006.05.11 [2.2.2]''\nin createExportPanel, removed call to addNotification() to no longer auto-refresh the list every time a tiddler is changed. Instead, call refreshExportList(0) only when the panel is first rendered and each time it is made visible. Prevents unneeded feedback messages from being displayed and increases overall document performance, since the listbox is no longer being updated each time a tiddler is saved.\n''2006.05.02 [2.2.1]''\nUse displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection. Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible. Reported by Paul Reiber.\n''2006.04.29 [2.2.0]''\nNew features: "Notes" are free-form text that is inserted in the header of a TWDIV export file. When exporting to a server, the "notify" checkbox indicates that server-side script processing should send an email message when the export file is stored on the server. Comma-separated addresses may be typed in, or pre-defined in the SiteNotify tiddler.\n''2006.03.29 [2.1.3]''\nadded calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.\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''2005.12.27 [2.0.0]''\nUpdate for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.24 [0.9.5]''\nMinor adjustments to CSS to force correct link colors regardless of TW stylesheet selection\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''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''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''2005.10.28 [0.9.0]''\nadded 'select opened tiddlers' feature\nBased on a suggestion by Geoff Slocock\n''2005.10.24 [0.8.3]''\nCorrected hijack of 'save changes' when using http:\n''2005.10.18 [0.8.2]''\nadded AJAX functions\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''2005.10.17 [0.8.0]''\nFirst pre-release.\n''2005.10.16 [0.7.0]''\nfilter by tags\n''2005.10.15 [0.6.0]''\nfilter by title/text\n''2005.10.14 [0.5.0]''\nexport to local file (DIV or XML)\n''2005.10.14 [0.4.0]''\nfilter by start/end date\n''2005.10.13 [0.3.0]''\npanel interaction\n''2005.10.11 [0.2.0]''\npanel layout\n''2005.10.10 [0.1.0]''\ncode framework\n''2005.10.09 [0.0.0]''\ndevelopment started\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: 2, revision: 3, date: new Date(2006,10,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 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 if (panel.style.display!="none") refreshExportList(0); // update list when panel is made visible\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 textarea { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\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;border:0 }\s\n#exportPanel .chk { width:auto;border:0 }\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-top:5px;">\s\nlocal path/filename<br>\s\n<input type="file" id="exportFilename" size=57 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-top:5px;">\s\n<table><tr><td align=left>\s\n server location, script, and parameters<br>\s\n</td><td align=right>\s\n <input type="checkbox" class="chk" id="exportNotify"\s\n onClick="document.getElementById(\s'exportSetNotifyPanel\s').style.display=this.checked?\s'block\s':\s'none\s'"> notify\s\n</td></tr></table>\s\n<input type="text" id="exportHTTPServerURL" onfocus="this.select()"><br>\s\n<div id="exportSetNotifyPanel" style="display:none">\s\n send email notices to<br>\s\n <input type="text" id="exportNotifyTo" onfocus="this.select()"><br>\s\n</div>\s\n</div><!--panel-->\s\n\s\n<!-- export to ftp server -->\s\n<div id="exportFTPPanel" style="display:none;margin-top:5px;">\s\n<table cellpadding="0" cellspacing="0" width="32%"><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="32%">\s\n username<br>\s\n <input type="text" id="exportFTPID" onfocus="this.select()"><br>\s\n</td><td width="32%">\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<!-- notes -->\s\nnotes<br>\s\n<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \s\n\s\n<!-- list of tiddlers -->\s\n<table><tr align="left"><td>\s\n select:\s\n <a href="JavaScript:;" id="exportSelectAll"\s\n onclick="onClickExportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="exportSelectChanges"\s\n onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\s\n changes </a> \s\n <a href="JavaScript:;" id="exportSelectOpened"\s\n onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\s\n opened </a> \s\n <a href="JavaScript:;" id="exportToggleFilter"\s\n onclick="onClickExportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align="right">\s\n <a href="JavaScript:;" id="exportListSmaller"\s\n onclick="onClickExportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="exportListLarger"\s\n onclick="onClickExportButton(this)" title="increase list size">\s\n + </a>\s\n</td></tr></table>\s\n<select id="exportList" multiple size="10" style="margin-bottom:5px;"\s\n onchange="refreshExportList(this.selectedIndex)">\s\n</select><br>\s\n</div><!--box-->\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 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 }\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 // get NOTIFY\n var theAddresses=store.getTiddlerText("SiteNotify");\n if (!theAddresses|| !theAddresses.length) theAddresses="SiteNotify";\n document.getElementById("exportNotifyTo").value=theAddresses;\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 // 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="";\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 document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));\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 document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(formatExportMessage(count,total));\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 document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(formatExportMessage(count,count));\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 document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(formatExportMessage(count,total));\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 formatExportMessage(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) { clearMessage(); displayMessage(formatExportMessage(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(tiddlers.length+" tiddlers in document", "",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.href;\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 title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());\n var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());\n var user = convertUnicodeToUTF8(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>"+convertUnicodeToUTF8(document.location.href)+"</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("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(regexpNewLine,"<br>")+"</pre>");\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><!--POST-BODY-START-->\sn<!--POST-BODY-END--></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 = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());\n var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());\n var user = convertUnicodeToUTF8(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>" + convertUnicodeToUTF8(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(convertUnicodeToUTF8(thisTiddler.saveToDiv()));\n if (theFormat=="DIV") out.push(convertUnicodeToUTF8(thisTiddler.title+"\sn"+thisTiddler.saveToDiv()));\n if (theFormat=="XML") out.push(convertUnicodeToUTF8(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 (document.getElementById('exportNotify').checked)\n theTarget+="¬ify="+encodeURIComponent(document.getElementById('exportNotifyTo').value);\n if (document.getElementById('exportNotes').value.trim().length)\n theTarget+="¬es="+encodeURIComponent(document.getElementById('exportNotes').value);\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
Like most wikis, TiddlyWiki supports a range of simplified character formatting:\n| !To get | !Type this |h\n| ''Bold'' | {{{''Bold''}}} |\n| --Strikethrough-- | {{{--Strikethrough--}}} |\n| __Underline__ | {{{__Underline__}}} (that's two underline characters) |\n| //Italic// | {{{//Italic//}}} |\n| Superscript: 2^^3^^=8 | {{{2^^3^^=8}}} |\n| Subscript: a~~ij~~ = -a~~ji~~ | {{{a~~ij~~ = -a~~ji~~}}} |\n| @@highlight@@ | {{{@@highlight@@}}} |\n<<<\nThe highlight can also accept CSS syntax to directly style the text:\n@@color:green;green coloured@@\n@@background-color:#ff0000;color:#ffffff;red coloured@@\n@@text-shadow:black 3px 3px 8px;font-size:18pt;display:block;margin:1em 1em 1em 1em;border:1px solid black;Access any CSS style@@\n<<<\n\n//For backwards compatibility, the following highlight syntax is also accepted://\n{{{\n@@bgcolor(#ff0000):color(#ffffff):red coloured@@\n}}}\n@@bgcolor(#ff0000):color(#ffffff):red coloured@@
!Windows Media Player\n\nThe following command lines produced AVI files that were playable with the default WinXP/SP2 installation of Windows Media Player: \n{{{\nffmpeg -i <inputfile.ext> -vcodec msmpeg4 -vtag MP43 -acodec mp3 <file.avi>\n}}}\nThis is the same as the infamous 'DIV3' DivX ;-) codec. However, if the '-vtag' option is omitted, the 'DIV3' tag will be inserted by default and WMP will reject the video format.\n{{{\nffmpeg -i <inputfile.ext> -vcodec msmpeg4v2 -acodec mp3 <file.avi> \n}}}\n use Microsoft MPEG-4v2 video\n{{{\nffmpeg -i <inputfile.ext> -vcodec wmv7 -acodec mp3 <file.avi> \n}}}\n use Microsoft WMV7\n\nNote that if you omit a specific '-acodec' audio coding format, FFmpeg will encode MP2 audio by default. This also works with the default WMP. \n\nNote also that MP3 encoding support is external to FFmpeg and must be configured appropriately. \n\nAnother compatible format that WMP can handle is vanilla MPEG. The command line: \n{{{\nffmpeg -i <inputfile.ext> <file.mpg> \n}}}\n will create a MPEG file with MPEG-1 video and MP2 audio. \n\n!Apple QuickTime Player\n\nThe following command lines produced QuickTime files that were playable with Apple QuickTime Player v6.5.2: \n{{{\nffmpeg -i <inputfile.ext> <file.mov>\nffmpeg -i <inputfile.ext> <file.mp4>\n}}}\nThese command lines will produce MPEG-4 QuickTime files with ISO MPEG-4 video and AAC audio.\n\nNote that AAC encoding support is external to FFmpeg and must be configured appropriately. \n\nAnother compatible format that Apple's QuickTime Player can handle is vanilla MPEG. The command line: \n{{{\nffmpeg -i <inputfile.ext> <file.mpg>\n}}}\n will create a MPEG file with MPEG-1 video and MP2 audio.
In OS X, the default permissions for items created by most programmes is -rw-r--r-- (644) for files and drwx-r-xr-x (755) for folders. This previous hint describes a useful method for changing the default permissions for GUI applications by adding an NSUmask property to the .GlobalPreferences.plist file to set a umask differring from the default 022. Unfortunately, this property only applies globally, and doesn't work when applied to the .plist files of individual applications.\n\nThis seems to be new in Tiger, but the default umask for the Finder can be set independently by adding a umask property to the com.apple.finder.plist file, either in an individual user's Preferences folder to apply to that user, or in the startup disk's main /Library/Preferences folder to apply to all users. The new permissions don't just apply to new folders -- they also apply to anything new created (but not copied) by the Finder including clippings, .xxxloc files, etc. However, note that folders created from the Save dialogues of other programs will have the default permissions of items created by that application.\n\nUnlike NSUmask, which requires the decimal equivalent of the octal representation of the umask, the Finder's umask takes the octal value directly. For example, to set the default permissions so that new folders created by all users on the computer are Group writable (drwxrwxr-x (775)), enter these commands in Terminal while logged into an Admin account:\n{{{\n$ defaults write /Library/Preferences/com.apple.finder umask -int 2\n$ chmod +r /Library/Preferences/com.apple.finder.plist\n}}}\nTo give just the current account's Finder more restrictive default permissions of drwx----- (700):\n{{{\n$ defaults write com.apple.finder umask -int 77\n}}}\nFor the change to take effect for any given logged-in user, it will be necessary to quit and restart the Finder (don't Force Quit or relaunch it), or log out and back in. In the future, hopefully more Apple applications will allow their umask to be changed without hacking the application package.\n\nNote that despite its title, this old hint describes something completely different -- changing the default umask for all users and all programs (not just "Finder") -- and as some of the comments suggest, is probably even scarier than setting a global NSUmask.
Here are some examples that show the usage of the write action in the ForEachTiddlerMacro.\n\n//''Select and Sort Examples''//\n* InClauseExamples\n* WhereClauseExamples\n* SortClauseExamples\n* ScriptClauseExamples\n//''Action Examples''//\n* AddToListActionExamples\n* WriteActionExamples\n\n\nOf cause you may also combine the examples, e.g. taking the whereClause of one example, the sortClause of a second and the action of a third.
//~~(Part of the [[ForEachTiddlerPlugin]])~~//\n\nCreate customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.\n\n''Syntax:'' \n|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|\n|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|\n|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|\n|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|\n|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\n\n''Using JavaScript''\n\nTo give you a lot of flexibility the [[ForEachTiddlerMacro]] uses JavaScript in its arguments. Even if you are not that familiar with JavaScript you may find forEachTiddler useful. Just have a look at the various ready-to-use [[ForEachTiddlerExamples]] and adapt them to your needs.\n\n''The Elements of the Macro''\n\nThe arguments of the ForEachTiddlerMacro consist of multiple parts, each of them being optional.\n\n<<slider chkFETInClause [[inClause]] "inClause" "inClause">>\n<<slider chkFETWhereClause [[whereClause]] "whereClause" "whereClause">>\n<<slider chkFETSortClause [[sortClause]] "sortClause" "sortClause">>\n<<slider chkFETScriptClause [[scriptClause]] "scriptClause" "scriptClause">>\n<<slider chkFETActions [[Action Specification]] "Action Specification" "Action Specification">>\n\n''Using Macros and ">" inside the forEachTiddler Macro''\n\nYou may use other macro calls into the expression, especially in the actionParameters. To avoid that the {{{>>}}} of such a macro call is misinterpreted as the end of the {{{<<forEachTiddler...>>}}} macro you must escape the {{{>>}}} of the inner macro with {{{$))}}} E.g. if you want to use {{{<<tiddler ...>>}}} inside the {{{forEachTiddler}}} macro you have to write {{{<<tiddler ...$))}}}.\n\nIn addition it is necessary to escape single {{{>}}} with the text {{{$)}}}.\n\n\n\nSee also [[ForEachTiddlerExamples]].
/***\n|''Name:''|ForEachTiddlerPlugin|\n|''Version:''|1.0.5 (2006-02-05)|\n|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''Macros:''|[[ForEachTiddlerMacro]] v1.0.5|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n!Description\n\nCreate customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.\n\n''Syntax:'' \n|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|\n|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|\n|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|\n|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|\n|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|\n|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\nSee details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].\n\n!Revision history\n* v1.0.5\n** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.\n** Support Firefox 1.5.0.1\n** Internal\n*** Make "JSLint" conform\n*** "Only install once"\n* v1.0.4 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.3 (2005-12-22)\n** Features: \n*** Write output to a file supports multi-byte environments (Thanks to Bram Chen) \n*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)\n** Enhancements:\n*** Improved error messages on InternetExplorer.\n* v1.0.2 (2005-12-10)\n** Features: \n*** context object also holds reference to store (TiddlyWiki)\n** Fixed Bugs: \n*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)\n* v1.0.1 (2005-12-08)\n** Features: \n*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".\n*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.\n*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).\n*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .\n*** Improved script evaluation (for where/sort clause and write scripts).\n* v1.0.0 (2005-11-20)\n** initial version\n\n!Code\n***/\n//{{{\n\n \n//============================================================================\n//============================================================================\n// ForEachTiddlerPlugin\n//============================================================================\n//============================================================================\n\n// Only install once\nif (!version.extensions.ForEachTiddlerPlugin) {\n\nversion.extensions.ForEachTiddlerPlugin = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), source: "http://tiddlywiki.abego-software.de/#ForEachTiddlergPlugin"};\n\n// For backward compatibility with TW 1.2.x\n//\nif (!TiddlyWiki.prototype.forEachTiddler) {\n TiddlyWiki.prototype.forEachTiddler = function(callback) {\n for(var t in this.tiddlers) {\n callback.call(this,t,this.tiddlers[t]);\n }\n };\n}\n\n//============================================================================\n// forEachTiddler Macro\n//============================================================================\n\nversion.extensions.forEachTiddler = {major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), provider: "http://tiddlywiki.abego-software.de"};\n\n// ---------------------------------------------------------------------------\n// Configurations and constants \n// ---------------------------------------------------------------------------\n\nconfig.macros.forEachTiddler = {\n // Standard Properties\n label: "forEachTiddler",\n prompt: "Perform actions on a (sorted) selection of tiddlers",\n\n // actions\n actions: {\n addToList: {},\n write: {}\n }\n};\n\n// ---------------------------------------------------------------------------\n// The forEachTiddler Macro Handler \n// ---------------------------------------------------------------------------\n\nconfig.macros.forEachTiddler.getContainingTiddler = function(e) {\n while(e && !hasClass(e,"tiddler"))\n e = e.parentNode;\n var title = e ? e.getAttribute("tiddler") : null; \n return title ? store.getTiddler(title) : null;\n};\n\nconfig.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n // config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);\n\n if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n // Parse the "in" clause\n var tiddlyWikiPath = undefined;\n if ((i < params.length) && params[i] == "in") {\n i++;\n if (i >= params.length) {\n this.handleError(place, "TiddlyWiki path expected behind 'in'.");\n return;\n }\n tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the where clause\n var whereClause ="true";\n if ((i < params.length) && params[i] == "where") {\n i++;\n whereClause = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the sort stuff\n var sortClause = null;\n var sortAscending = true; \n if ((i < params.length) && params[i] == "sortBy") {\n i++;\n if (i >= params.length) {\n this.handleError(place, "sortClause missing behind 'sortBy'.");\n return;\n }\n sortClause = this.paramEncode(params[i]);\n i++;\n\n if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {\n sortAscending = params[i] == "ascending";\n i++;\n }\n }\n\n // Parse the script\n var scriptText = null;\n if ((i < params.length) && params[i] == "script") {\n i++;\n scriptText = this.paramEncode((i < params.length) ? params[i] : "");\n i++;\n }\n\n // Parse the action. \n // When we are already at the end use the default action\n var actionName = "addToList";\n if (i < params.length) {\n if (!config.macros.forEachTiddler.actions[params[i]]) {\n this.handleError(place, "Unknown action '"+params[i]+"'.");\n return;\n } else {\n actionName = params[i]; \n i++;\n }\n } \n \n // Get the action parameter\n // (the parsing is done inside the individual action implementation.)\n var actionParameter = params.slice(i);\n\n\n // --- Processing ------------------------------------------\n try {\n this.performMacro({\n place: place, \n inTiddler: tiddler,\n whereClause: whereClause, \n sortClause: sortClause, \n sortAscending: sortAscending, \n actionName: actionName, \n actionParameter: actionParameter, \n scriptText: scriptText, \n tiddlyWikiPath: tiddlyWikiPath});\n\n } catch (e) {\n this.handleError(place, e);\n }\n};\n\n// Returns an object with properties "tiddlers" and "context".\n// tiddlers holds the (sorted) tiddlers selected by the parameter,\n// context the context of the execution of the macro.\n//\n// The action is not yet performed.\n//\n// @parameter see performMacro\n//\nconfig.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {\n\n var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);\n\n var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;\n context["tiddlyWiki"] = tiddlyWiki;\n \n // Get the tiddlers, as defined by the whereClause\n var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);\n context["tiddlers"] = tiddlers;\n\n // Sort the tiddlers, when sorting is required.\n if (parameter.sortClause) {\n this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);\n }\n\n return {tiddlers: tiddlers, context: context};\n};\n\n// Returns the (sorted) tiddlers selected by the parameter.\n//\n// The action is not yet performed.\n//\n// @parameter see performMacro\n//\nconfig.macros.forEachTiddler.getTiddlers = function(parameter) {\n return this.getTiddlersAndContext(parameter).tiddlers;\n};\n\n// Performs the macros with the given parameter.\n//\n// @param parameter holds the parameter of the macro as separate properties.\n// The following properties are supported:\n//\n// place\n// whereClause\n// sortClause\n// sortAscending\n// actionName\n// actionParameter\n// scriptText\n// tiddlyWikiPath\n//\n// All properties are optional. \n// For most actions the place property must be defined.\n//\nconfig.macros.forEachTiddler.performMacro = function(parameter) {\n var tiddlersAndContext = this.getTiddlersAndContext(parameter);\n\n // Perform the action\n var actionName = parameter.actionName ? parameter.actionName : "addToList";\n var action = config.macros.forEachTiddler.actions[actionName];\n if (!action) {\n this.handleError(parameter.place, "Unknown action '"+actionName+"'.");\n return;\n }\n\n var actionHandler = action.handler;\n actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);\n};\n\n// ---------------------------------------------------------------------------\n// The actions \n// ---------------------------------------------------------------------------\n\n// Internal.\n//\n// --- The addToList Action -----------------------------------------------\n//\nconfig.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {\n // Parse the parameter\n var p = 0;\n\n // Check for extra parameters\n if (parameter.length > p) {\n config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);\n return;\n }\n\n // Perform the action.\n var list = document.createElement("ul");\n place.appendChild(list);\n for (var i = 0; i < tiddlers.length; i++) {\n var tiddler = tiddlers[i];\n var listItem = document.createElement("li");\n list.appendChild(listItem);\n createTiddlyLink(listItem, tiddler.title, true);\n }\n};\n\n// Internal.\n//\n// --- The write Action ---------------------------------------------------\n//\nconfig.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {\n // Parse the parameter\n var p = 0;\n if (p >= parameter.length) {\n this.handleError(place, "Missing expression behind 'write'.");\n return;\n }\n\n var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);\n p++;\n\n // Parse the "toFile" option\n var filename = null;\n var lineSeparator = undefined;\n if ((p < parameter.length) && parameter[p] == "toFile") {\n p++;\n if (p >= parameter.length) {\n this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");\n return;\n }\n \n filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));\n p++;\n if ((p < parameter.length) && parameter[p] == "withLineSeparator") {\n p++;\n if (p >= parameter.length) {\n this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");\n return;\n }\n lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);\n p++;\n }\n }\n \n // Check for extra parameters\n if (parameter.length > p) {\n config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);\n return;\n }\n\n // Perform the action.\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);\n var count = tiddlers.length;\n var text = "";\n for (var i = 0; i < count; i++) {\n var tiddler = tiddlers[i];\n text += func(tiddler, context, count, i);\n }\n \n if (filename) {\n if (lineSeparator !== undefined) {\n lineSeparator = lineSeparator.replace(/\s\sn/mg, "\sn").replace(/\s\sr/mg, "\sr");\n text = text.replace(/\sn/mg,lineSeparator);\n }\n saveFile(filename, convertUnicodeToUTF8(text));\n } else {\n var wrapper = createTiddlyElement(place, "span");\n wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);\n }\n};\n\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n// Internal.\n//\nconfig.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {\n return {\n place : placeParam, \n whereClause : whereClauseParam, \n sortClause : sortClauseParam, \n sortAscending : sortAscendingParam, \n script : scriptText,\n actionName : actionNameParam, \n actionParameter : actionParameterParam,\n tiddlyWikiPath : tiddlyWikiPathParam,\n inTiddler : inTiddlerParam\n };\n};\n\n// Internal.\n//\n// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of \n// the given path.\n//\nconfig.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {\n if (!idPrefix) {\n idPrefix = "store";\n }\n var lenPrefix = idPrefix.length;\n \n // Read the content of the given file\n var content = loadFile(this.getLocalPath(path));\n if(content === null) {\n throw "TiddlyWiki '"+path+"' not found.";\n }\n \n // Locate the storeArea div's\n var posOpeningDiv = content.indexOf(startSaveArea);\n var posClosingDiv = content.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1)) {\n throw "File '"+path+"' is not a TiddlyWiki.";\n }\n var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);\n \n // Create a "div" element that contains the storage text\n var myStorageDiv = document.createElement("div");\n myStorageDiv.innerHTML = storageText;\n myStorageDiv.normalize();\n \n // Create all tiddlers in a new TiddlyWiki\n // (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)\n var tiddlyWiki = new TiddlyWiki();\n var store = myStorageDiv.childNodes;\n for(var t = 0; t < store.length; t++) {\n var e = store[t];\n var title = null;\n if(e.getAttribute)\n title = e.getAttribute("tiddler");\n if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)\n title = e.id.substr(lenPrefix);\n if(title && title !== "") {\n var tiddler = tiddlyWiki.createTiddler(title);\n tiddler.loadFromDiv(e,title);\n }\n }\n tiddlyWiki.dirty = false;\n\n return tiddlyWiki;\n};\n\n\n \n// Internal.\n//\n// Returns a function that has a function body returning the given javaScriptExpression.\n// The function has the parameters:\n// \n// (tiddler, context, count, index)\n//\nconfig.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {\n var script = context["script"];\n var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";\n var fullText = (script ? script+";" : "")+functionText+";theFunction;";\n return eval(fullText);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {\n var result = [];\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);\n tiddlyWiki.forEachTiddler(function(title,tiddler) {\n if (func(tiddler, context, undefined, undefined)) {\n result.push(tiddler);\n }\n });\n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {\n var message = "Extra parameter behind '"+actionName+"':";\n for (var i = firstUnusedIndex; i < parameter.length; i++) {\n message += " "+parameter[i];\n }\n this.handleError(place, message);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {\n var result = \n (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) \n ? 0\n : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)\n ? -1 \n : +1; \n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {\n var result = \n (tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) \n ? 0\n : (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)\n ? +1 \n : -1; \n return result;\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {\n // To avoid evaluating the sortClause whenever two items are compared \n // we pre-calculate the sortValue for every item in the array and store it in a \n // temporary property ("forEachTiddlerSortValue") of the tiddlers.\n var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);\n var count = tiddlers.length;\n var i;\n for (i = 0; i < count; i++) {\n var tiddler = tiddlers[i];\n tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);\n }\n\n // Do the sorting\n tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);\n\n // Delete the temporary property that holds the sortValue. \n for (i = 0; i < tiddlers.length; i++) {\n delete tiddlers[i].forEachTiddlerSortValue;\n }\n};\n\n\n// Internal.\n//\nconfig.macros.forEachTiddler.trace = function(message) {\n displayMessage(message);\n};\n\n// Internal.\n//\nconfig.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {\n var message ="<<"+macroName;\n for (var i = 0; i < params.length; i++) {\n message += " "+params[i];\n }\n message += ">>";\n displayMessage(message);\n};\n\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.forEachTiddler.createErrorElement = function(place, exception) {\n var message = (exception.description) ? exception.description : exception.toString();\n return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);\n};\n\n// Internal.\n//\n// @param place [may be null]\n//\nconfig.macros.forEachTiddler.handleError = function(place, exception) {\n if (place) {\n this.createErrorElement(place, exception);\n } else {\n throw exception;\n }\n};\n\n// Internal.\n//\n// Encodes the given string.\n//\n// Replaces \n// "$))" to ">>"\n// "$)" to ">"\n//\nconfig.macros.forEachTiddler.paramEncode = function(s) {\n var reGTGT = new RegExp("\s\s$\s\s)\s\s)","mg");\n var reGT = new RegExp("\s\s$\s\s)","mg");\n return s.replace(reGTGT, ">>").replace(reGT, ">");\n};\n\n// Internal.\n//\n// Returns the given original path (that is a file path, starting with "file:")\n// as a path to a local file, in the systems native file format.\n//\n// Location information in the originalPath (i.e. the "#" and stuff following)\n// is stripped.\n// \nconfig.macros.forEachTiddler.getLocalPath = function(originalPath) {\n // Remove any location part of the URL\n var hashPos = originalPath.indexOf("#");\n if(hashPos != -1)\n originalPath = originalPath.substr(0,hashPos);\n // Convert to a native file format assuming\n // "file:///x:/path/path/path..." - pc local file --> "x:\spath\spath\spath..."\n // "file://///server/share/path/path/path..." - FireFox pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."\n // "file://server/share/path/path/path..." - pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n var localPath;\n if(originalPath.charAt(9) == ":") // pc local file\n localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file:///") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(7));\n else if(originalPath.indexOf("file:/") === 0) // mac/unix local file\n localPath = unescape(originalPath.substr(5));\n else // pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\s\s"); \n return localPath;\n};\n\n// ---------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// ---------------------------------------------------------------------------\n//\nsetStylesheet(\n ".forEachTiddlerError{color: #ffffff;background-color: #880000;}",\n "forEachTiddler");\n\n//============================================================================\n// End of forEachTiddler Macro\n//============================================================================\n\n\n//============================================================================\n// String.startsWith Function\n//============================================================================\n//\n// Returns true if the string starts with the given prefix, false otherwise.\n//\nversion.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.startsWith = function(prefix) {\n var n = prefix.length;\n return (this.length >= n) && (this.slice(0, n) == prefix);\n};\n\n\n\n//============================================================================\n// String.endsWith Function\n//============================================================================\n//\n// Returns true if the string ends with the given suffix, false otherwise.\n//\nversion.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.endsWith = function(suffix) {\n var n = suffix.length;\n return (this.length >= n) && (this.right(n) == suffix);\n};\n\n\n//============================================================================\n// String.contains Function\n//============================================================================\n//\n// Returns true when the string contains the given substring, false otherwise.\n//\nversion.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nString.prototype.contains = function(substring) {\n return this.indexOf(substring) >= 0;\n};\n\n//============================================================================\n// Array.indexOf Function\n//============================================================================\n//\n// Returns the index of the first occurance of the given item in the array or \n// -1 when no such item exists.\n//\n// @param item [may be null]\n//\nversion.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.indexOf = function(item) {\n for (var i = 0; i < this.length; i++) {\n if (this[i] == item) {\n return i;\n }\n }\n return -1;\n};\n\n//============================================================================\n// Array.contains Function\n//============================================================================\n//\n// Returns true when the array contains the given item, otherwise false. \n//\n// @param item [may be null]\n//\nversion.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.contains = function(item) {\n return (this.indexOf(item) >= 0);\n};\n\n//============================================================================\n// Array.containsAny Function\n//============================================================================\n//\n// Returns true when the array contains at least one of the elements \n// of the item. Otherwise (or when items contains no elements) false is returned.\n//\nversion.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.containsAny = function(items) {\n for(var i = 0; i < items.length; i++) {\n if (this.contains(items[i])) {\n return true;\n }\n }\n return false;\n};\n\n\n//============================================================================\n// Array.containsAll Function\n//============================================================================\n//\n// Returns true when the array contains all the items, otherwise false.\n// \n// When items is null false is returned (even if the array contains a null).\n//\n// @param items [may be null] \n//\nversion.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};\n//\nArray.prototype.containsAll = function(items) {\n for(var i = 0; i < items.length; i++) {\n if (!this.contains(items[i])) {\n return false;\n }\n }\n return true;\n};\n\n\n} // of "install only once"\n\n// Used Globals (for JSLint) ==============\n// ... DOM\n/*global document */\n// ... TiddlyWiki Core\n/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, \n displayMessage, endSaveArea, hasClass, loadFile, saveFile, \n startSaveArea, store, wikify */\n//}}}\n\n\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n\n
A FormTemplate is used with the [[FormTiddlerPlugin]]. It is a tiddler that contains one or more HTML INPUT elements and defines the layout of a form. \n\nOther tiddlers can reference a FormTemplate through the [[FormTiddlerMacro]].\n\n(See [[FormTiddler Introduction]])
|!Example|!Comment|\n|[[SimpleForm|SimpleForm (Card 1)]]|Three forms, using a simple template with "username" and "password" fields|\n|[[BiggerForm|BiggerForm (Card 1)]]|Three forms, using a template with all supported Form input elements|\n|[[Bugreports]]|Use forms and filtered lists to maintain bug reports|\n|[[Contacts|JoeBlock]]|Manage your contacts in forms|\n
The [[FormTiddlerPlugin]] allows you to enter your data in a form and store the form's data in your tiddlers.\n\n(For more information on tiddler data see the [[DataTiddlerPlugin]].)\n\n//''Define ~FormTemplate''//\n\nWhen you want to enter data in a form you first have to define a [[FormTemplate]] tiddler. A FormTemplate tiddler is a tiddler that contains named HTML INPUT elements (such as textfields, password fields, lists etc.) that define the stuff that should be edited in the form. E.g. you may have a FormTemplate that looks like this:\n\n<html>\n <b>Name:</b><br/>\n <input name=userName type=text /><br/>\n <b>Password:</b><br/>\n <input name=pwd type=password /><br/>\n</html>\n\nThe correspond HTML text looks like this\n{{{\n<html>\n <b>Name:</b><br/>\n <input name=userName type=text /><br/>\n <b>Password:</b><br/>\n <input name=pwd type=password /><br/>\n</html>\n}}}\n\nThe name of the INPUT element is also the name of the data field it is editing. E.g. a text field defined like this: \n{{{\n<input name=userName type=text />\n}}}\nwill edit the data field "userName" of the tiddler.\n\n\nYou are free to layout the INPUT elements as you like, but don't add a "form" element around them and don't define 'onchange' handlers, since this will be done automatically by the {{{<<formTiddler ...>>}}} macro.\n\n\n//''Use ~FormTemplates (through the {{{<<formTiddler ...>>}}} macro)''//\n\nIn a second step you add the {{{<<formTiddler ...>>}}} macro to tiddlers that should be edited. In the macro you are referencing the [[FormTemplate]] that should be used to edit the tiddler's data. You may refer to the same FormTemplate tiddler in as many tiddlers as you like. Every such tiddler displays the same INPUT elements as the FormTemplate, but with the "data" of each individual tiddler.\n\nIn addition you may more than one {{{<<formTiddler...>>}}} macro call in one tiddler. Just make sure that the names of the elements in the referenced FormTemplate tiddlers do not collide. This feature may be useful if you want to construct a larger input form from a set of smaller FormTemplates.\n\nYou can easily create tiddlers with an embedded {{{<<formTiddler...>>}}} macro call using the [[<<newTiddlerWithForm...>>|NewTiddlerWithFormMacro]] macro. The macro shows a button similar to the "new tiddler" button and creates the requested tiddler, ready to enter data. For details see NewTiddlerWithFormMacro.\n\n\n//''"Structured" and "Free" Data''//\n\nTypically you will edit a tiddler that uses the {{{<<formTiddler...>>}}} macro through the form. But you are free to also edit the tiddler "as usual", through the build-in edit feature. I.e. you may mix "structured data" (as entered through the form) with "free data". I.e. on a "Contact" tiddler you may add an image to the tiddler, or add extra links to related persons. Or you add more tags. Just make sure that you don't modify the {{{<data>...</data>}}} section of the tiddler, since this contains the data maintained by the form.\n\nAlso notice that since the data entered in the forms is stored in the tiddler's text (in the {{{<data>...</data>}}} section) using the "search" feature will also find the texts you entered in the forms (even though it will not hilite the texts in the fields).\n\n\n//''Applications''//\n\nUsing the [[FormTiddlerPlugin]] it is easy to manage things like:\n* [[Contacts]]\n* [[Bugreports]]\n* ~ToDo Lists\n* and many more.\n\nSince a FormTemplate is typically used for many tiddlers of the same kind you may also consider using the ForEachTiddlerMacro to collect data across multiple tiddlers (e.g. to get a list of all contacts, a summary page for the bug reports etc.)\n\n(See also [[FormTiddler Examples]])\n\n\n//''HTML Elements''//\n\nFor those not that familiar with the HTML INPUT elements here a short overview with HTML snippets. \n|!Type|!HTML Example|!Comment|\n|button|{{{<input name=btn type=button value="Just a button" />}}}|no data|\n|checkbox|{{{<input name=isVIP type=checkbox />is VIP}}}||\n|file|{{{<input name=attachment type=file />}}}|The "file" input element typically does not restore the path of the previously selected file. Nevertheless the path of the file is stored in the tiddler.|\n|hidden|{{{<input name=hiddenValue type=hidden value="This is a hidden value" />}}}||\n|password|{{{<input name=pwd type=password />}}}|The data entered in a "password" field is stored as clear text in the tiddler.|\n|radio|{{{<input name=level type=radio value="Beginner" />Beginner<input name=level type=radio value="Expert" />Expert<input name=level type=radio value="Guru" />Guru}}}||\n|reset|{{{<input name=btnReset type=reset />}}}|no data|\n|select-one|{{{<select name=browser ><option>Firefox<option>Internet Explorer<option>Opera<option>Other</select >}}}||\n|select-multiple|{{{<select name=music MULTIPLE ><option> R&B <option> Jazz <option> Blues <option> New Age</select >}}}||\n|submit|{{{<input name=btnSubmit type=submit />}}}|no data|\n|text|{{{<input name=userName type=text/>}}}||\n|textarea|{{{<TEXTAREA name=notes rows=4 cols=80 ></TEXTAREA>}}}||\n\nFor details consult the Web or a textbook on HTML editing.
The {{{<<formTiddler ...>>}}} macro defined by the FormTiddlerPlugin. \n\nWhen a tiddler T1 references the (FormTemplate) tiddler T2 in the FormTiddlerMacro, the data of T1 can be edited through the INPUT elements defined by T2.
/***\n<<checkForDataTiddlerPlugin>>\n|''Name:''|FormTiddlerPlugin|\n|''Version:''|1.0.5 (2006-02-24)|\n|''Source:''|http://tiddlywiki.abego-software.de/#FormTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''Macros:''|formTiddler, checkForDataTiddlerPlugin, newTiddlerWithForm|\n|''Requires:''|DataTiddlerPlugin|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n!Description\nUse form-based tiddlers to enter your tiddler data using text fields, listboxes, checkboxes etc. (All standard HTML Form input elements supported).\n\n''Syntax:'' \n|>|{{{<<}}}''formTiddler'' //tiddlerName//{{{>>}}}|\n|//tiddlerName//|The name of the FormTemplate tiddler to be used to edit the data of the tiddler containing the macro.|\n\n|>|{{{<<}}}''newTiddlerWithForm'' //formTemplateName// //buttonLabel// [//titleExpression// [''askUser'']] {{{>>}}}|\n|//formTemplateName//|The name of the tiddler that defines the form the new tiddler should use.|\n|//buttonLabel//|The label of the button|\n|//titleExpression//|A (quoted) JavaScript String expression that defines the title (/name) of the new tiddler.|\n|''askUser''|Typically the user is not asked for the title when a title is specified (and not yet used). When ''askUser'' is given the user will be asked in any case. This may be used when the calculated title is just a suggestion that must be confirmed by the user|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\nFor details and how to use the macros see the [[introduction|FormTiddler Introduction]] and the [[examples|FormTiddler Examples]].\n\n!Revision history\n* v1.0.5 (2006-02-24)\n** Removed "debugger;" instruction\n* v1.0.4 (2006-02-07)\n** Bug: On IE no data is written to data section when field values changed (thanks to KenGirard for reporting)\n* v1.0.3 (2006-02-05)\n** Bug: {{{"No form template specified in <<formTiddler>>"}}} when using formTiddler macro on InternetExplorer (thanks to KenGirard for reporting)\n* v1.0.2 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.1 (2005-12-22)\n** Features: \n*** Support InternetExplorer\n*** Added newTiddlerWithForm Macro\n* v1.0.0 (2005-12-14)\n** initial version\n\n!Code\n***/\n//{{{\n\n//============================================================================\n//============================================================================\n// FormTiddlerPlugin\n//============================================================================\n//============================================================================\n\n\nversion.extensions.FormTiddlerPlugin = {\n major: 1, minor: 0, revision: 5,\n date: new Date(2006, 2, 24), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#FormTiddlerPlugin"\n};\n\n// For backward compatibility with v1.2.x\n//\nif (!window.story) window.story=window; \nif (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; } \n\n//============================================================================\n// formTiddler Macro\n//============================================================================\n\n// -------------------------------------------------------------------------------\n// Configurations and constants \n// -------------------------------------------------------------------------------\n\nconfig.macros.formTiddler = {\n // Standard Properties\n label: "formTiddler",\n version: {major: 1, minor: 0, revision: 4, date: new Date(2006, 2, 7)},\n prompt: "Edit tiddler data using forms",\n\n // Define the "setters" that set the values of INPUT elements of a given type\n // (must match the corresponding "getter")\n setter: { \n button: function(e, value) {/*contains no data */ },\n checkbox: function(e, value) {e.checked = value;},\n file: function(e, value) {try {e.value = value;} catch(e) {/* ignore, possibly security error*/}},\n hidden: function(e, value) {e.value = value;},\n password: function(e, value) {e.value = value;},\n radio: function(e, value) {e.checked = (e.value == value);},\n reset: function(e, value) {/*contains no data */ },\n "select-one": function(e, value) {config.macros.formTiddler.setSelectOneValue(e,value);},\n "select-multiple": function(e, value) {config.macros.formTiddler.setSelectMultipleValue(e,value);},\n submit: function(e, value) {/*contains no data */},\n text: function(e, value) {e.value = value;},\n textarea: function(e, value) {e.value = value;}\n },\n\n // Define the "getters" that return the value of INPUT elements of a given type\n // Return undefined to not store any data.\n getter: { \n button: function(e, value) {return undefined;},\n checkbox: function(e, value) {return e.checked;},\n file: function(e, value) {return e.value;},\n hidden: function(e, value) {return e.value;},\n password: function(e, value) {return e.value;},\n radio: function(e, value) {return e.checked ? e.value : undefined;},\n reset: function(e, value) {return undefined;},\n "select-one": function(e, value) {return config.macros.formTiddler.getSelectOneValue(e);},\n "select-multiple": function(e, value) {return config.macros.formTiddler.getSelectMultipleValue(e);},\n submit: function(e, value) {return undefined;},\n text: function(e, value) {return e.value;},\n textarea: function(e, value) {return e.value;}\n }\n};\n\n\n// -------------------------------------------------------------------------------\n// The formTiddler Macro Handler \n// -------------------------------------------------------------------------------\n\nconfig.macros.formTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!config.macros.formTiddler.checkForExtensions(place, macroName)) {\n return;\n }\n \n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n\n // get the name of the form template tiddler\n var formTemplateName = undefined;\n if (i < params.length) {\n formTemplateName = params[i];\n i++;\n }\n\n if (!formTemplateName) {\n config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");\n return;\n }\n\n\n // --- Processing ------------------------------------------\n\n // Get the form template text. \n // (This contains the INPUT elements for the form.)\n var formTemplateTiddler = store.getTiddler(formTemplateName);\n if (!formTemplateTiddler) {\n config.macros.formTiddler.createErrorElement(place, "Form template '" + formTemplateName + "' not found.");\n return;\n }\n var templateText = formTemplateTiddler.text;\n if(!templateText) {\n // Shortcut: when template text is empty we do nothing.\n return;\n }\n\n // Get the name of the tiddler containing this "formTiddler" macro\n // (i.e. the tiddler, that will be edited and that contains the data)\n var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(place);\n\n // Append a "form" element. \n var formName = "form"+formTemplateName+"__"+tiddlerName;\n var e = document.createElement("form");\n e.setAttribute("name", formName);\n place.appendChild(e);\n\n // "Embed" the elements defined by the templateText (i.e. the INPUT elements) \n // into the "form" element we just created\n wikify(templateText, e);\n\n // Initialize the INPUT elements.\n config.macros.formTiddler.initValuesAndHandlersInFormElements(formName, DataTiddler.getDataObject(tiddlerName));\n}\n\n\n// -------------------------------------------------------------------------------\n// Form Data Access \n// -------------------------------------------------------------------------------\n\n// Internal.\n//\n// Initialize the INPUT elements of the form with the values of their "matching"\n// data fields in the tiddler. Also setup the onChange handler to ensure that\n// changes in the INPUT elements are stored in the tiddler's data.\n//\nconfig.macros.formTiddler.initValuesAndHandlersInFormElements = function(formName, data) {\n // config.macros.formTiddler.trace("initValuesAndHandlersInFormElements(formName="+formName+", data="+data+")");\n\n // find the form\n var form = config.macros.formTiddler.findForm(formName);\n if (!form) {\n return;\n }\n\n try {\n var elems = form.elements;\n for (var i = 0; i < elems.length; i++) {\n var c = elems[i];\n \n var setter = config.macros.formTiddler.setter[c.type];\n if (setter) {\n var value = data[c.name];\n if (value != null) {\n setter(c, value);\n }\n c.onchange = onFormTiddlerChange;\n } else {\n config.macros.formTiddler.displayFormTiddlerError("No setter defined for INPUT element of type '"+c.type+"'. (Element '"+c.name+"' in form '"+formName+"')");\n }\n }\n } catch(e) {\n config.macros.formTiddler.displayFormTiddlerError("Error when updating elements with new formData. "+e);\n }\n}\n\n\n// Internal.\n//\n// @return [may be null]\n//\nconfig.macros.formTiddler.findForm = function(formName) {\n // We must manually iterate through the document's forms, since\n // IE does not support the "document[formName]" approach\n\n var forms = window.document.forms;\n for (var i = 0; i < forms.length; i++) {\n var form = forms[i];\n if (form.name == formName) {\n return form;\n }\n }\n\n return null;\n}\n\n\n// Internal.\n//\nconfig.macros.formTiddler.setSelectOneValue = function(element,value) {\n var n = element.options.length;\n for (var i = 0; i < n; i++) {\n element.options[i].selected = element.options[i].value == value;\n }\n}\n\n// Internal.\n//\nconfig.macros.formTiddler.setSelectMultipleValue = function(element,value) {\n var values = {};\n for (var i = 0; i < value.length; i++) {\n values[value[i]] = true;\n }\n \n var n = element.length;\n for (var i = 0; i < n; i++) {\n element.options[i].selected = !(!values[element.options[i].value]);\n }\n}\n\n// Internal.\n//\nconfig.macros.formTiddler.getSelectOneValue = function(element) {\n var i = element.selectedIndex;\n return (i >= 0) ? element.options[i].value : null;\n}\n\n// Internal.\n//\nconfig.macros.formTiddler.getSelectMultipleValue = function(element) {\n var values = [];\n var n = element.length;\n for (var i = 0; i < n; i++) {\n if (element.options[i].selected) {\n values.push(element.options[i].value);\n }\n }\n return values;\n}\n\n\n\n// -------------------------------------------------------------------------------\n// Helpers \n// -------------------------------------------------------------------------------\n\n// Internal.\n//\nconfig.macros.formTiddler.checkForExtensions = function(place,macroName) {\n if (!version.extensions.DataTiddlerPlugin) {\n config.macros.formTiddler.createErrorElement(place, "<<" + macroName + ">> requires the DataTiddlerPlugin. (You can get it from http://tiddlywiki.abego-software.de/#DataTiddlerPlugin)");\n return false;\n }\n return true;\n}\n\n// Internal.\n//\n// Displays a trace message in the "TiddlyWiki" message pane.\n// (used for debugging)\n//\nconfig.macros.formTiddler.trace = function(s) {\n displayMessage("Trace: "+s);\n}\n\n// Internal.\n//\n// Display some error message in the "TiddlyWiki" message pane.\n//\nconfig.macros.formTiddler.displayFormTiddlerError = function(s) {\n alert("FormTiddlerPlugin Error: "+s);\n}\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.formTiddler.createErrorElement = function(place, message) {\n return createTiddlyElement(place,"span",null,"formTiddlerError",message);\n}\n\n// Internal.\n//\n// Returns the name of the tiddler containing the given element.\n// \nconfig.macros.formTiddler.getContainingTiddlerName = function(element) {\n return story.findContainingTiddler(element).id.substr(7);\n}\n\n// -------------------------------------------------------------------------------\n// Event Handlers \n// -------------------------------------------------------------------------------\n\n// This function must be called by the INPUT elements whenever their\n// data changes. Typically this is done through an "onChange" handler.\n//\nfunction onFormTiddlerChange (e) {\n // config.macros.formTiddler.trace("onFormTiddlerChange "+e);\n\n if (!e) var e = window.event;\n\n var target = resolveTarget(e);\n var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(target);\n var getter = config.macros.formTiddler.getter[target.type];\n if (getter) {\n var value = getter(target);\n DataTiddler.setData(tiddlerName, target.name, value);\n } else {\n config.macros.formTiddler.displayFormTiddlerError("No getter defined for INPUT element of type '"+target.type+"'. (Element '"+target.name+"' used in tiddler '"+tiddlerName+"')");\n }\n}\n\n// ensure that the function can be used in HTML event handler\nwindow.onFormTiddlerChange = onFormTiddlerChange;\n\n\n// -------------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// -------------------------------------------------------------------------------\n\nsetStylesheet(\n ".formTiddlerError{color: #ffffff;background-color: #880000;}",\n "formTiddler");\n\n\n//============================================================================\n// checkForDataTiddlerPlugin Macro\n//============================================================================\n\nconfig.macros.checkForDataTiddlerPlugin = {\n // Standard Properties\n label: "checkForDataTiddlerPlugin",\n version: {major: 1, minor: 0, revision: 0, date: new Date(2005, 12, 14)},\n prompt: "Check if the DataTiddlerPlugin exists"\n}\n\nconfig.macros.checkForDataTiddlerPlugin.handler = function(place,macroName,params) {\n config.macros.formTiddler.checkForExtensions(place, config.macros.formTiddler.label);\n}\n\n\n\n//============================================================================\n// newTiddlerWithForm Macro\n//============================================================================\n\nconfig.macros.newTiddlerWithForm = {\n // Standard Properties\n label: "newTiddlerWithForm",\n version: {major: 1, minor: 0, revision: 1, date: new Date(2006, 1, 6)},\n prompt: "Creates a new Tiddler with a <<formTiddler ...>> macro"\n}\n\nconfig.macros.newTiddlerWithForm.handler = function(place,macroName,params) {\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n\n // get the name of the form template tiddler\n var formTemplateName = undefined;\n if (i < params.length) {\n formTemplateName = params[i];\n i++;\n }\n\n if (!formTemplateName) {\n config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");\n return;\n }\n\n // get the button label\n var buttonLabel = undefined;\n if (i < params.length) {\n buttonLabel = params[i];\n i++;\n }\n\n if (!buttonLabel) {\n config.macros.formTiddler.createErrorElement(place, "No button label specified in <<" + macroName + ">>.");\n return;\n }\n\n // get the (optional) tiddlerName script and "askUser"\n var tiddlerNameScript = undefined;\n var askUser = false;\n if (i < params.length) {\n tiddlerNameScript = params[i];\n i++;\n\n if (i < params.length && params[i] == "askUser") {\n askUser = true;\n i++;\n }\n }\n\n // --- Processing ------------------------------------------\n\n if(!readOnly) {\n var onClick = function() {\n var tiddlerName;\n if (tiddlerNameScript) {\n try {\n tiddlerName = eval(tiddlerNameScript);\n } catch (ex) {\n }\n }\n if (!tiddlerName || askUser) {\n tiddlerName = prompt("Please specify a tiddler name.", askUser ? tiddlerName : "");\n }\n while (tiddlerName && store.getTiddler(tiddlerName)) {\n tiddlerName = prompt("A tiddler named '"+tiddlerName+"' already exists.\sn\sn"+"Please specify a tiddler name.", tiddlerName);\n }\n\n // tiddlerName is either null (user canceled) or a name that is not yet in the store.\n if (tiddlerName) {\n var body = "<<formTiddler [["+formTemplateName+"]]>>";\n var tags = [];\n store.saveTiddler(tiddlerName,tiddlerName,body,config.options.txtUserName,new Date(),tags);\n story.displayTiddler(null,tiddlerName,1);\n }\n }\n\n createTiddlyButton(place,buttonLabel,buttonLabel,onClick);\n }\n}\n\n//}}}\n\n\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n
http://pasky.or.cz/~pasky/dev/retty/
<html><iframe src="http://mail.google.com/mail/?ui=html&zy=n" width=100% height=600></iframe></html>
*Linux Radio Shows - http://www.thelinuxlink.net/
{{{\nsetenv LIBS "/usr/local/lib/libncurses.so -Wl,-rpath -Wl,/usr/local/lib"\nsetenv TERMLIBS "-L/usr/local/lib -lncurses -R/usr/local/lib"\nsetenv LD_LIBRARY_PATH "/opt/gnu/lib"\n\n--with-gnu-as --with-as=/opt/gnu/bin/as\n--with-gnu-ld --with-ld=/opt/gnu/bin/ld\n}}}
[[GNU/Linux]]\nGentooPortage\nXenGentoo
[[elogviewer|http://forums.gentoo.org/viewtopic-t-441228-start-0-postdays-0-postorder-asc-highlight-.html]]\n\nelogs saved in /var/log/portage/elog\n\nPORTAGE_ELOG_CLASSES="warn error log"\nPORTAGE_ELOG_SYSTEM="save"\n
{{{\n<<forEachTiddler \n where\n 'tiddler.tags.contains("systemConfig")'\n write\n '((index == 0) ? "" : ", ")+"[["+tiddler.title+"]]"'\n>>\n}}}\n''//Explaination//''\nThe initial idea to accomplish the task is use a write parameter list this: {{{"[["+tiddler.name+"]], "}. But to avoid that a comma is appended after the final tiddler the write parameter is a little bit more complex and refers to the build-in variable {{index}}.\n\n''//Result://''\n<<forEachTiddler\n where\n 'tiddler.tags.contains("systemConfig")'\n write\n '((index == 0) ? "" : ", ")+"[["+tiddler.title+"]]"'\n>>\n\n\nSee Also ForEachTiddlerExamples.
/***\n|''Name:''|GotoPlugin|\n|''Source:''|http://www.TiddlyTools.com/#GotoPlugin|\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\n''View a tiddler by typing its title and pressing //enter//.'' Input just enough to uniquely match a single tiddler title and ''press //enter// to auto-complete the title for you!!'' If multiple titles match your input, a list is displayed. You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press //escape// to close the listbox to resume typing. When the listbox is ''//not//'' being displayed, press //escape// to clear the current text input and start over.\n\nNote: ''At any time, you can move the focus directly to the text input field by using the ~ALT-G keyboard shortcut.''\n!!!!!Example\n<<<\nsyntax: {{{<<goto quiet inputstyle liststyle>>}}}\nAll parameters are optional.\n* ''quiet'' prevents //automatic// display of the list as each character is typed. To view the list when ''quiet'', use //down// or //enter//.\n* ''inputstyle'' and ''liststyle'' are CSS declarations that modify the default input and listbox styles. Note: styles containing spaces must be surrounded by ({{{"..."}}} or {{{'...'}}}) or ({{{[[...]]}}}).\n{{{<<goto>>}}}\n<<goto>>\n{{{<<goto quiet>>}}}\n<<goto quiet>>\n{{{<<goto width:20em width:20em>>}}}\n<<goto width:20em width:20em>>\n<<<\n!!!!!Configuration\n<<<\nThe following ~TiddlyWiki search options (see AdvancedOptions) are applied when matching tiddler titles:\n><<option chkRegExpSearch>> use regular expressions (text patterns)\n><<option chkCaseSensitiveSearch>> use case sensitive matching\nYou can also create a tiddler tagged with <<tag systemConfig>> to control listing of tiddlers/shadows/tags, as well as the maximum height of the listbox. //The default values are shown below://\n//{{{\nconfig.macros.goto.includeTiddlers=true;\nconfig.macros.goto.includeShadows=true;\nconfig.macros.goto.includeTags=true;\nconfig.macros.goto.listMaxSize=10;\n//}}}\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''GotoPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revisions\n<<<\n''2006.05.10 [1.1.2]'' when filling listbox, set selection to 'heading' item... auto-select first tiddler title when down/enter moves focus into listbox\n''2006.05.08 [1.1.1]'' added accesskey ("G") to input field html (also set when field gets focus). Also, inputKeyHandler() skips non-printing/non-editing keys. \n''2006.05.08 [1.1.0]'' added heading to listbox for better feedback (also avoids problems with 1-line droplist)\n''2006.05.07 [1.0.0]'' list matches against tiddlers/shadows/tags. input field auto-completion... 1st enter=complete matching input (or show list)... 2nd enter=view tiddler. optional "quiet" param controls when listbox appears.\n''2006.05.06 [0.5.0]'' added handling for enter (13), escape(27), and down(40) keys. Change 'ondblclick' to 'onclick' for list handler to view tiddlers (suggested by Florian Cauvin - prevents unintended trigger of tiddler editor). shadow titles inserted into list instead of appended to the end.\n''2006.05.05 [0.0.0]'' started\n<<<\n!!!!!Credits\n>This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n!!!!!Code\n***/\n//{{{\nversion.extensions.goto= {major: 1, minor: 1, revision: 2, date: new Date(2006,5,10)};\nconfig.macros.goto= { \n handler:\n function(place,macroName,params) {\n var quiet=(params[0] && params[0]=="quiet"); if (quiet) params.shift();\n var instyle=params.shift(); if (!instyle) instyle="";\n var liststyle=params.shift(); if (!liststyle) liststyle="";\n createTiddlyElement(place,"span").innerHTML\n =this.html.replace(/%quiet%/,quiet).replace(/%instyle%/,instyle).replace(/%liststyle%/,liststyle);\n },\n\n html:\n '<form onsubmit="return false" style="display:inline;margin:0;padding:0">\s\n <input name=goto type=text autocomplete="off" accesskey="G" style="%instyle%"\s\n title="enter a tiddler title"\s\n onfocus="this.setAttribute(\s'accessKey\s',\s'G\s'); this.select();"\s\n onkeyup="return config.macros.goto.inputKeyHandler(event,this,this.form.list,%quiet%);">\s\n <select name=list style="%liststyle%;display:none;position:absolute"\s\n onchange="if (!this.selectedIndex) this.selectedIndex=1;"\s\n onblur="this.style.display=\s'none\s';"\s\n onkeyup="return config.macros.goto.selectKeyHandler(event,this,this.form.goto);"\s\n onclick="return config.macros.goto.openItem(this.value,this.form.goto,this);">\s\n </select>\s\n </form>',\n \n getItems:\n function() {\n var items=[];\n var tiddlers=store.reverseLookup("tags","excludeSearch",false,"title");\n if (this.includeTiddlers) for(var t=0; t<tiddlers.length; t++) items.push(tiddlers[t].title);\n if (this.includeShadows) for (var t in config.shadowTiddlers) items.pushUnique(t);\n if (this.includeTags) { var tags=store.getTags(); for(var t=0; t<tags.length; t++) items.pushUnique(tags[t][0]); }\n return items;\n },\n includeTiddlers: true, includeShadows: true, includeTags: true,\n\n getItemSuffix:\n function(t) {\n if (store.tiddlerExists(t)) return ""; // tiddler\n if (store.isShadowTiddler(t)) return " (shadow)"; // shadow\n return " (tag)"; // tag \n },\n\n openItem:\n function(title,here,list) {\n if (!title.length) return; here.value=title; list.style.display='none'; story.displayTiddler(null,title); return false;\n },\n\n inputKeyHandler:\n function(event,here,list,quiet) {\n var key=event.keyCode;\n // non-printing chars... bubble up, except: backspace=8, enter=13, escape=27, space=32, down=40, delete=46\n if (key<48) switch(key) { case 8: case 13: case 27: case 32: case 40: case 46: break; default: return true; }\n // escape... hide list (2nd esc=reset input)\n if (key==27) { if (list.style.display=="none") here.value=here.defaultValue; else list.style.display="none"; return false; }\n // blank input... if down/enter... fall through (list all)... else, hide list\n if (!here.value.length && !(key==40 || key==13)) { list.style.display="none"; return false; }\n // find matching items...\n var pattern=config.options.chkRegExpSearch?here.value:here.value.escapeRegExp();\n var re=new RegExp(pattern,config.options.chkCaseSensitiveSearch?"mg":"img");\n var found = []; var items=this.getItems(); for(var t=0; t<items.length; t++) if(items[t].search(re)!=-1) found.push(items[t]);\n // matched one item... enter... not *exact* match... autocomplete input field\n if (found.length==1 && quiet && key==13 && here.value!=found[0]) { list.style.display="none"; here.value=found[0]; return false; }\n // no match/exact match... enter... create/show it\n if (found.length<2 && key==13) return this.openItem(found.length?found[0]:here.value,here,list);\n // quiet/no match... hide list...\n list.style.display=(!quiet && found.length)?"block":"none";\n // no matches... key bubbles up\n if (!found.length) return true;\n // down/enter... show/move to list...\n if (key==40 || key==13) { list.style.display="block"; list.focus(); }\n // list is showing... fill list...\n if (list.style.display!="none") {\n while (list.length > 0) list.options[0]=null; // clear list...\n found.sort();\n list.options[0]=new Option(found.length==1?this.listMatchMsg:this.listHeading.format([found.length]),"",false,false);\n for (var t=0; t<found.length; t++) // fill list...\n list.options[t+1]=new Option(found[t]+this.getItemSuffix(found[t]),found[t],false,false);\n list.size=(found.length<this.listMaxSize?found.length:this.listMaxSize)+1; // resize list...\n list.selectedIndex=(key==40 || key==13)?1:0;\n }\n return true; // key bubbles up\n },\n listMaxSize: 10,\n listHeading: 'Found %0 matching titles:',\n listMatchMsg: 'Press enter to open tiddler...',\n\n selectKeyHandler:\n function(event,list,editfield) {\n if (event.keyCode==27) // escape... hide list, move to edit field\n { editfield.focus(); list.style.display="none"; return false; }\n if (event.keyCode==13 && list.value.length) // enter... view selected item\n { this.openItem(list.value,editfield,list); return false; }\n return true;\n }\n}\n//}}}
/***\n|Name|HelloWorldMacro|\n|Created by|SimonBaird|\n|Location|http://simonbaird.com/mptw/#HelloWorldMacro|\n|Version|1.0.3|\n|Requires|~TW2.x|\n!Description\nIt's a Hello World TiddlyWiki macro.\n\n!History\n* 03-Mar-06, version 1.0.3, added version.extensions data\n* 13-Jan-06, version 1.0.2, added shout macro example\n* 11-Jan-06, version 1.0.1, updated for ~TW2.0\n\n!Examples\n|!Source|!Output|h\n|{{{<<helloWorld dude>>}}}|<<helloWorld dude>>|\n|{{{<<helloWorld 'to everyone'>>}}}|<<helloWorld 'to everyone'>>|\n(You can use (single or double) quotes or double square brackets for params with spaces)\n\n!Notes\nThis is intended to help you get started with customising your TW. To make the macro work you have to give this tiddler a tag of systemConfig then save and reload. To learn more about customising Tiddlywiki? Look at other people's plugins or... click View, Source in your browser and start reading. :)\n\n!Code\n***/\n//{{{\n\n// this part is not actually required but a very useful\n// if you think anyone else might use your plugin\nversion.extensions.HelloWorldMacro = { major: 1, minor: 0, revision: 3, date: new Date(2006,3,3),\n source: "http://simonbaird.com/mptw/#HelloWorldMacro"\n};\n\nconfig.macros.helloWorld = {};\nconfig.macros.helloWorld.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n var who = params.length > 0 ? params[0] : "world";\n wikify("Hello //" + who + "// from the '" + macroName + "' macro in tiddler [[" + tiddler.title + "]].", place);\n}\n\n// a one liner...\nconfig.macros.shout = { handler: function(place,name,params) { wikify("//''@@font-size:5em;color:#696;"+ params[0] + "!@@''//", place); } };\n\n\n//}}}\n\n/***\n\n!Another example\n{{{<<shout Yeah>>}}}\n\n<<shout 'Yeah'>>\n\n***/\n
/***\n| Name:|HideWhenPlugin|\n| Description:|Allows conditional inclusion/exclusion in templates|\n| Version:|6.9.3|\n| Date:|30-Sep-2006|\n| Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\nFor use in ViewTemplate and EditTemplate. Eg\n{{{<div macro="showWhen tiddler.tags.contains('Task')">[[TaskToolbar]]</div>}}}\n{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}\n***/\n//{{{\nmerge(config.macros,{\n\n hideWhen: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n if (eval(paramString)) {\n removeChildren(place);\n place.parentNode.removeChild(place);\n }\n }},\n\n showWhen: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n config.macros.hideWhen.handler(place,macroName,params,wikifier,'!('+paramString+')',tiddler);\n }}\n\n});\n\n//}}}\n\n
Linksys linksys:admin http://192.168.101.1/\nWestell admin:westell http://192.168.1.1/
[[1&1 Internet Inc|http://www.1and1.com]]\n[[Site 5|http://site5.com]]\n[[Powweb|http://www.powweb.com]]\n[[bluehost|http://bluehost.com]]\n[[Yurx|http://yurx.com/]]\n[[Dayana Hosting|http://www.dayanahost.com/]]\n[[ASP Spider.Net|http://www.aspspider.net/]]\n
Need a dividing line? Type four hyphens in a row on a line by themselves.\n----\nThat'll keep your sheep and goats separated.\n\nHere's the ridiculously simple code to create that line:\n{{{\n----\n}}}
/%Javascript cross-domain data access security issues%/\n{{menubox{{{small{\n__Javascript cross-domain data access security issues__\n\nCertain JavaScript features require expanded "cross-domain" privileges, normally restricted for use with ''signed'' scripts. You can set your browser to allow or disallow a signed script based on the digital sigature of the originator (or ''principal'') of the signed script. However, for an //''unsigned''// script to use expanded privileges, a ''codebase principal'', derived from the origin of the script rather than from verifying a digital signature of a certificate, must be used.\n>''Codebase principals are disabled by default; to enable them in FireFox, go to "about:config" in your browser, and set {{{signed.applets.codebase_principal_support}}} to {{{true}}} (//note: other browsers' settings may vary... if applicable, try adding //{{{user_pref("signed.applets.codebase_principal_support", true);}}}// to your browser's "preferences" file//).''\nWhen an unsigned script requests expanded privileges with codebase principals enabled, a dialog box advises that the script has not been digitally signed, and asks for permission to grant privileges based on the URL (the 'codebase principal') rather than signed/verified author information.\n<<<\n| Privilege |Description |\n| UniversalBrowserRead|Allows reading of privileged data from the browser. This allows the script to pass the same origin check for any document.|\n| UniversalBrowserWrite|Allows modification of privileged data in a browser. This allows the script to pass the same origin check for any document.|\n| UniversalBrowserAccess|Allows both reading and modification of privileged data from the browser. This allows the script to pass the same origin check for any document.|\n| UniversalFileRead|Allows a script to read any files stored on hard disks or other storage media connected to your computer.|\n| UniversalPreferencesRead|Allows the script to read preferences using the navigator.preference method.|\n| UniversalPreferencesWrite|Allows the script to set preferences using the navigator.preference method.|\n| UniversalSendMail|Allows the program to send mail in the user's name.|\n<<<\nThe following features require expanded privileges:\n* Setting a file upload widget requires UniversalFileRead.\n* Submitting a form to a mailto: or news: URL requires UniversalSendMail.\n* Using an about: URL other than about:blank requires UniversalBrowserRead.\n* event object: Setting any property requires UniversalBrowserWrite.\n* DragDrop event: Getting the value of the data property requires UniversalBrowserRead.\n* history object: Getting the value of any property requires UniversalBrowserRead.\n* navigator object:\n** Getting the value of a preference using the preference method requires UniversalPreferencesRead.\n** Setting the value of a preference using the preference method requires UniversalPreferencesWrite.\n* window object: Allow of the following operations require UniversalBrowserWrite.\n** Adding or removing the directory bar, location bar, menu bar, personal bar, scroll bar, status bar, or toolbar.\n** Using the methods in the following table under the indicated circumstances\n<<<\n| enableExternalCapture|To capture events in pages loaded from different servers. Follow this method with captureEvents.|\n| close|To unconditionally close a browser window.|\n| moveBy|To move a window off the screen.|\n| moveTo|To move a window off the screen.|\n| open|To create a window smaller than 100 x 100 pixels or larger than the screen can accommodate by using innerWidth, innerHeight, outerWidth, and outerHeight.<<br>>To place a window off screen by using screenX and screenY.<<br>>To create a window without a titlebar by using titlebar.<<br>>To use alwaysRaised, alwaysLowered, or z-lock for any setting.<<br>>|\n| resizeTo|To resize a window smaller than 100 x 100 pixels or larger than the screen can accommodate.|\n| resizeBy|To resize a window smaller than 100 x 100 pixels or larger than the screen can accommodate.|\n<<<\n**Setting the properties in the following table under the indicated circumstances:\n<<<\n| innerWidth|To set the inner width of a window to a size smaller than 100 x 100 or larger than the screen can accommodate.|\n| innerHeight|To set the inner height of a window to a size smaller than 100 x 100 or larger than the screen can accommodate.|\n<<<\n}}}}}}
Let's say that, for some reason, you need to have a single Tiddler with multiple headings. Put the headings on lines by themselves and add an exclamation point (!) at the beginning of the line. If you want a subheading, use two exclamation points, like so:\n\n!Heading1\n!!Subheading1\n!!!Subsubheading1\n\nHere's the code for the above stack of subheadings:\n{{{\n!Heading1\n!!Subheading1\n!!!Subsubheading1\n}}}
"But!" you interrupt, "what if I want to use mixed case and //not// create a tiddler, like if I'm talking about ~JavaScript?" Easy: Just precede the word with a single tilde (~). \n\n{{{\n~JavaScript\n}}}
An embedded image looks like this:\n\n[img[Dog shakes hand with soldier|http://www.blogjones.com/Images/dogsoldier.jpg][http://www.blogjones.com/Images/dogsoldier.jpg]]\n\nHere's how the code works:\n{{{\n[img[alternate text|filename or URL][link]]\n}}}\n\nThe Alternate Text and Link parameters are optional. You can use just {{{img[filename]}}} if you want, although it is better to include alternate text in case the image does not load for some reason.\n\n[>img[Same dog, floating right|http://www.blogjones.com/Images/dogsoldier.jpg][http://www.blogjones.com/Images/dogsoldier.jpg]You can also set images to float to the left or the right of the text in your tiddler by using {{{[<img[...]}}} to float left or {{{[>img[...]}}} to float right. \n\nTwo notes about using images:\n#First, if you add images to the wiki, the wiki becomes less portable--you have to make sure that the wiki can get to the images you link to. \n#Second, it's considered rude to "hotlink" images on other people's servers. Don't just directly link to someone else's image; download it onto your computer and upload it back to your own server or to a free image host like [[Image Shack|http://www.imageshack.us/]].
TiddlyWiki supports all kinds of formatting options:\n*You can create ''Bold'' text by enclosing it in pairs of single quotes:\n{{{\n''bold text''\n}}}\n\n*You can create ==Strikethrough== text by enclosing it in pairs of equal signs:\n{{{\n==strikethrough text==\n}}}\n\n*You can __Underline__ text by enclosing it in pairs of underscores:\n{{{\n__underlined text__\n}}}\n\n*You can create //Italic// text by enclosing it in pairs of forward slashes:\n{{{\n//italic text//\n}}}\n\n*You can create ^^superscript^^ text by enclosing it in pairs of carets:\n{{{\n^^superscript text^^\n}}}\n\n*You can create ~~subscript~~ text by enclosing it in pairs of tildes:\n{{{\n~~subscript text~~\n}}}\n\n*You can @@highlight text@@ by enclosing it in pairs of at-signs.\n{{{\n@@highlighted text@@\n}}}\n\n*You can also change many other CSS attributes by adding arguments to the highlight command. For example, you can change the text color to @@color:red;red@@ or give it a background-color of @@background-color:#0000FF;color:white;blue@@.\n{{{\n@@CSS attributes separated by semicolons;text@@\n}}}\n\nYou can find out more about CSS from the excellent [[w3schools tutorial|http://w3schools.com/css/default.asp]].\n\n*Finally, you can add new CSS classes to the Tiddlywiki so that you can style a number of items with the same CSS formatting. Simply add the new class to the StyleSheet [[ShadowTiddler|ShadowTiddlers]], such as:\n{{{\n.moveover{\nmargin-left:120px;\n}\n}}}\nThen, when you want to use that CSS class, use the following formatting:\n{{{\n{{classname{text to be formatted}}}\n}}}\n{{moveover{So, for example, this paragraph has been formatted using the moveover CSS class.}}}
You are by no means confined to this standard blue and white TiddlyWiki style. It's fairly easy to restructure and reformat this page to meet your needs if you know a little CSS and HTML. (If you don't know CSS and HTML, now's a great time to learn. Check out http://www.w3schools.com for more information on those topics.)\n\nAll you have to do to alter the style and structure of this page is to change a few ShadowTiddlers. The primary ones you're going to be interested in are the following:\n*PageTemplate -- Contains the overall structure of the page, including the gradient macro for the masthead.\n*EditTemplate -- Contains the structure and order of the tiddler editor screen\n*ViewTemplate -- Contains the structure and order of the tiddler view screen\n*StyleSheetColors -- Contains the CSS for the colors used by the TiddlyWiki\n*StyleSheetLayout -- Contains the CSS for the layout of the TiddlyWiki\n*StyleSheetPrint -- Contains the CSS used when printing from the TiddlyWiki\n\n!Example\nSo, let's say for example that you want the tag list to appear below your tiddlers instead of floating to the right of them. This is the process that you'd follow:\n\n1. Open the "StyleSheetLayout" tiddler\n2. Edit this tiddler and scroll down to the line marked "{{{.tagged {}}}"\n3. Delete the "{{{float:right;}}}" from this CSS class.\n4. Add the following code to the tiddler:\n{{{\n.tagged li, .tagged ul {\ndisplay:inline;\n}\n}}}\n5. Click "Done" and close the StyleSheetLayout tiddler.\n6. Open and edit the "ViewTemplate" tiddler\n7. Move the line marked "{{{<div class='tagged' macro='tags'></div>}}}" to the end of the list.\n8. Click "Done" and close the ViewTemplate tiddler\n9. [[Save you changes|HowToSaveYourChanges]] and refresh the page. Your tags should now be after each post and on a single line.
/%Display a tiddler in a floating, moveable, sizeable panel%/\n{{menubox{{{small{\n__Display a tiddler in a floating, moveable, sizeable panel__\n\nUsing a combination of NestedSlidersPlugin and MoveablePanelPlugin, you can quickly turn any tiddler into a floating panel that can be moved/sized/folded/maximized in response to simple mouse actions (drag, shift-drag, double-click) and/or menu commands.\n\n!!!!! example\n{{{\nsyntax:\n+++^width^[label]\n <<moveablePanel>>TiddlerTitle\n----\n <<tiddler TiddlerTitle>>\n===\n}}}\n+++^30em^[click here to see SiteSubtitle in a floating panel]\n <<moveablePanel>>SiteSubtitle\n----\n This is the site subtitle:\n\n <<tiddler SiteSubtitle>>\n===\n{{{\n+++^30em^[click here to see SiteSubtitle in a floating panel]\n <<moveablePanel>>SiteSubtitle\n----\n This is the site subtitle:\n\n <<tiddler SiteSubtitle>>\n===\n}}}\n*the {{{^width^}}} portion of the slider syntax declares the start of a "floating slider" panel, where //width// is any valid CSS measurement (e.g., "30em", "200px", "60%", "3in", etc.). Use ^auto^, {{{^^}}}, or just {{{^}}} to allow the panel to resize as needed to fit the contents.\n>{{fine{hint: if you use 'auto' sizing, the panel width can change unexpectedly due to the 'float:right' properties of the moveable panel dynamic menus. To bypass this behavior, always specify a fixed panel size when including the {{{<<moveablePanel>>}}} macro}}}\n*The {{{<<moveablePanel>>}}} macro adds move/size functions (mouse actions and menus) to the floating slider panel, and should be the first item in the slider panel contents, immediately following the "start slider" syntax.\n>{{fine{hint: you can follow the {{{<<moveablePanel>>}}} macro with some "title text" for the panel and then a horizontal line (----) to create a "titlebar" appearance for the panel. When appropriate, this panel "title" should include a link to the tiddler containing the source for the panel content, so that the reader can easily view that content using a standard tiddler display.}}}\n*Use the {{{<<tiddler TiddlerName>>}}} macro to insert contents from another tiddler. You can put //any// tiddler content you want inside a floating panel: e.g. ''add formatting or other content //surrounding// the included tiddler'', or just ''enter content directly, without including another tiddler'' at all...\n}}}}}}
I'm sure you've noticed by now that there are a lot of places where words are stuck together, like HowToMakeATiddler or EasyToEdit. Here's the reason for that: Whenever you type in a word that's mixed case (also known as a WikiWord), TiddlyWiki will automatically create a link to a [[Tiddler]] with that title. \n\nTry it! Doubleclick on this [[Tiddler]] to go into editing mode and put a few words together in the space below. When you've got a WikiWord made up, click "done."\n\n----\n\n----\n\nSee how TiddlyWiki automatically converted your WikiWord into an italicized link? Click on it. \n\nYou should see a new [[Tiddler]] with your WikiWord as the title and the words "This tiddler doesn't yet exist. Double-click to create it" underneath it. If you double click, write something in the text box, and click "done", a new [[Tiddler]] will be created with the title you've given it. Now if you write that same WikiWord in any other [[Tiddler]], TiddlyWiki will automatically create a link to that same entry.\n\n"But," you say, "what if I want to make a tiddler that's just one word? Or one that doesn't use mixed case?" Open up editing mode, and enclose the word you want to turn into a tiddler in double brackets, like these:\n{{{\n[[Non-Wiki Word or Phrase]]\n}}}\n<<tiddler HowToDewikifyAWikiWord>>\nThat's all there is to it.
You aren't restricted to only linking to your own tiddlers: Here's how you link to something offsite, like the [[TiddlyWiki Home Page|http://www.tiddlywiki.com]].\n\n{{{\n[[text|url]]\n}}}
Lists are one of the easiest things to do in TiddlyWiki, and that's saying a lot. Put an asterisk (*) at the beginning of any line you want added to a bulleted list. If you use two or three asterisks, you'll create second and third level bullets. Like this:\n\n*Entry One\n**Sub-entry A\n***Sub-sub-entry i\n***Sub-sub-entry ii\n**Sub-entry B\n*Entry Two\n*Entry Three\n\nHere's the code for the above list:\n\n{{{\n*Entry One\n**Sub-entry A\n***Sub-sub-entry i\n***Sub-sub-entry ii\n**Sub-entry B\n*Entry Two\n*Entry Three\n}}}\n\nNumbered lists are pretty easy too: Just use number signs (#'s) instead of asterisks:\n\n#Entry One\n##Sub-entry A\n###Sub-sub-entry i\n###Sub-sub-entry ii\n##Sub-entry B\n#Entry Two\n#Entry Three\n\nAnd, once again, here's the code:\n\n{{{\n#Entry One\n##Sub-entry A\n###Sub-sub-entry i\n###Sub-sub-entry ii\n##Sub-entry B\n#Entry Two\n#Entry Three\n}}}
You can create a table by enclosing text in sets of vertical bars (||, or shift-backslash on your keyboard). \n|!Headings: add an exclamation point (!) right after the vertical bar.|!Heading2|!Heading3|\n|Row 1, Column 1|Row 1, Column 2|Row 1, Column 3|\n|>|>|Have one row span multiple columns by using a >|\n|Have one column span multiple rows by using a ~|>| Use a space to right-align text in a cell|\n|~|>| Enclose text in a cell with spaces to center it |\n|>|>|bgcolor(lightgreen):Add color to a cell using bgcolor(yourcolorhere):|\n|Add a caption by ending the table with a vertical bar followed by a c|c\n\nHere's the code for the above table:\n{{{\n|!Headings: add an exclamation point (!) right after the vertical bar.|!Heading2|!Heading3|\n|Row 1, Column 1|Row 1, Column 2|Row 1, Column 3|\n|>|>|Have one row span multiple columns by using a >|\n|Have one column span multiple rows by using a ~|>| Use a space to right-align text in a cell|\n|~|>| Enclose text in a cell with spaces to center it |\n|>|>|bgcolor(lightgreen):Add color to a cell using bgcolor(yourcolorhere):|\n|Add a caption by ending the table with a vertical bar followed by a c|c\n}}}
/%Override cookie-based option settings with 'hard-coded' values%/\n{{menubox{{{small{\n__Override cookie-based option settings with 'hard-coded' values__\n\nYou can override //any// cookie-based config.option.* setting by ''hard-coding'' the desired value into a systemConfig tiddler (i.e., a plugin).\n\nFor example, suppose you prefer to set EnableAnimations to false by default, so that the first time your readers visit your document, they won't have to disable it themselves... all you need to do is to create a tiddler containing the following line of javascript:\n{{{\nconfig.options.chkAnimate=false;\n}}}\nthen, tag that tiddler with<<tag systemConfig>>to make it a plugin... the javascript it contains will be invoked //after// you save and reload the document. At "load-time", option values are initialized in this order:\n<<<\n# hard-coded values in the TiddlyWiki core code.\n# values from cookies (read from the browser)\n# values set by plugins\n<<<\nBecause plugins are executed last, any values they set supercede the values loaded from the browser's cookies or set by the core code.\n>{{fine{note: plugins are executed in //alphanumeric// order (based on tiddler title). Most of the time this does not cause any problems. However, if a plugin references an option value during it's load-time initialization, you will need to make sure that the tiddler containing the overridden cookie values is executed //first// by giving it a tiddler title that is sorted ahead of the dependent plugin's title.}}}\nexample: ConfigTweaks\n}}}}}}
/%Reposition slider panels within a tiddler%/\n{{menubox{{{small{\n__Reposition slider panels within a tiddler__\n\nWhen you select a slider button, everything following that slider button is 'pushed down' the page so that the corresponding slider panel can be displayed. However, when several slider buttons are on the same line (e.g. to create a horizontal 'menubar'), opening one of these sliders 'splits' the menubar, so that any menu items following the open slider are pushed down below that slider.\n\nTo preserve the single-row layout of slider buttons, you can use InlineJavascriptPlugin to ''set a specific element ID within each slider panel'', and then ''move the identified elements by directly DOM manipulation'' so that all panels //follow// the slider buttons, instead of being placed //in-between// them.\n!!!!! example\nwithout stacking:\n+++[label1]\n stuff1\n=== +++[label2]\n stuff2\n=== +++[label3]\n stuff3\n=== +++[label4]\n stuff4\n===\n{{{\n+++[label1]\n stuff1\n=== +++[label2]\n stuff2\n=== +++[label3]\n stuff3\n=== +++[label4]\n stuff4\n===\n}}}\n----\nwith stacking:\n+++[label1]\n stuff1\n===<script>place.lastChild.id="panel1"</script> +++[label2]\n stuff2\n===<script>place.lastChild.id="panel2"</script> +++[label3]\n stuff3\n===<script>place.lastChild.id="panel3"</script> +++[label4]\n stuff4\n===<script>place.lastChild.id="panel4"</script><script>\n place.insertBefore(document.getElementById("panel1"),null);\n place.insertBefore(document.getElementById("panel2"),null);\n place.insertBefore(document.getElementById("panel3"),null);\n place.insertBefore(document.getElementById("panel4"),null);\n</script>\n{{{\n+++[label1]\n stuff1\n===<script>place.lastChild.id="panel1"</script> +++[label2]\n stuff2\n===<script>place.lastChild.id="panel2"</script> +++[label3]\n stuff3\n===<script>place.lastChild.id="panel3"</script> +++[label4]\n stuff4\n===<script>place.lastChild.id="panel4"</script><script>\n place.insertBefore(document.getElementById("panel1"),null);\n place.insertBefore(document.getElementById("panel2"),null);\n place.insertBefore(document.getElementById("panel3"),null);\n place.insertBefore(document.getElementById("panel4"),null);\n</script>\n}}}\n}}}}}}
You can most easily save changes if you're using Firefox or Internet Explorer: Safari and Opera can be used, with some [[caveats|http://www.tiddlywiki.com/#Safari%20Opera]]. Also, if you're using Internet Explorer on Windows XP you might run into [[ServicePack2Problems|http://www.tiddlywiki.com/#ServicePack2Problems]]. Your best option is to use Firefox.\n\nIn order to save your changes, you ''have to have a copy of TiddlyWiki saved on your hard drive''. Find out how to get your copy in EasyToCarry. \n# Once you have a copy of TiddlyWiki, open it in your browser.\n# Click the 'options' button on the right and set your username.\n# [[Edit|EasyToEdit]], [[create|HowToMakeATiddler]] and delete as many tiddlers as you want.\n# Click the 'save changes' button on the right to save your changes \n** Note that Firefox will give you as many as three security warnings. It's OK, just click Allow or check the "don't warn me again" box.\n# TiddlyWiki will make a backup copy of the existing file, and then replace it with the new version.\n
If you want to quote a long passage of someone else's work, you'll need blockquotes. At the line before the passage begins, add three less-than signs (<<<). On the line after the passage ends, add three more less-than signs. Like so:\n\n[[Bill Whittle|http://www.ejectejecteject.com/archives/000091.html]] said:\n\n<<<\nWe need a map. Several are for sale. How do we choose?\n\nWell, it seems like a good idea to choose the map that best conforms to the coastline we see unveiling before us. We choose the map that best fits the territory. We choose the map that best matches ''reality'' – the objective, external, indisputable reality of bays and promontories, capes and gulfs and rivers and shoals.\n\nWe can, indeed, lay out competing philosophies on the table, and see where each conforms to reality and where it does not. No maps are without distortions; none of these are likely to be, either. And one map may conform perfectly to the coastline in one area, and be dreadfully amiss in another. We can cut and paste them as we wish. This is too important for us to be arguing about who is right – all our energies must go to //getting it// right.\n\nAnd before we start, we must agree to one thing, and one thing only: we will never be so full of arrogance and blinded by pride that we dare confront a place where the map does not match the coastline, and proclaim that ''the coastline must be wrong.''\n\nNavigation by means of reason and logic, taking sightings from historical landmarks and always keeping the firm hand of common sense on the wheel, can steer us clear of these dangerous and confusing times. This sort of thinking, what is essentially scientific thinking, is a new tool, relatively speaking. It is a powerful tool, one that makes powerful demands of us, asking us to forgo pride and ego and preconception. It asks us, as blind men and women in the darkness of the present, to walk into the future not by closing our eyes and glibly imagining a map that is to our liking, but rather to learn to navigate like bats and dolphins, pinging our surroundings, interrogating nature and history at every turn, finding fixed points of reference that we can use to triangulate where we are and where we are headed. \n<<<\n\nHere's the code for a blockquote:\n\n{{{\n<<<\nQuoted text.\n<<<\n}}}
Here are some examples that show the usage of the inClause in the ForEachTiddlerMacro.\n\n<<forEachTiddler\n where\n 'tiddler.tags.contains("inClauseExample")'\n>>\n\nSee also ForEachTiddlerExamples.
/***\n''InlineJavascriptPlugin for TiddlyWiki version 1.2.x and 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.elsdesign.com/tiddlywiki/#InlineJavascriptPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nInsert Javascript executable code directly into your tiddler content. Lets you ''call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.\n!!!!!Usage\n<<<\nWhen installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered. By including a label="..." parameter in the initial {{{<script>}}} marker, the plugin will create a button linked to an 'onclick' script that will be executed only when that specific button is clicked. \n\n''External script source files:''\nYou can also load javascript from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="http://www.elsdesign.com/tiddlywiki/demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.\n\n''Defining javascript functions and libraries:''\nAlthough the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).\n\nTo ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.\n\nSince the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.\n\n''Creating dynamic tiddler content''\nAn important difference between this implementation of embedded scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document:\n* In a typical web document, you use the document.write() function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.\n* However, in a TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and completely replaces the entire TiddlyWiki document in your browser window.\n\n''To produce dynamically embedded content within a tiddler, your javascript should explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display.''\n\n//Note: your script code is automatically 'wrapped' inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.//\n\n''Accessing the TiddlyWiki DOM''\nThe plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.\n\nAccess to this DOM element allows you to create scripts that can:\n* vary their actions based upon the specific location in which they are embedded\n* access 'tiddler-relative' information (use findContainingTiddler(place))\n* perform direct DOM manipulations (when returning wikified text is not enough)\n<<<\n!!!!!Examples\n<<<\nan "alert" message box:\n{{{\n<script>alert('InlineJavascriptPlugin: this is a demonstration message');</script>\n}}}\n\n\ndynamic output:\n{{{\n<script>return (new Date()).toString();</script>\n}}}\n<script>return (new Date()).toString();</script>\n\nwikified dynamic output:\n{{{\n<script>return "link to current user: [["+config.options.txtUserName+"]]";</script>\n}}}\n<script>return "link to current user: [["+config.options.txtUserName+"]]";</script>\n\ndynamic output using 'place' to get size information for current tiddler\n{{{\n<script>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\n}}}\n<script>\n if (!window.story) window.story=window;\n var title=story.findContainingTiddler(place).id.substr(7);\n return title+" is using "+store.getTiddlerText(title).length+" bytes";\n</script>\n\ncreating an 'onclick' button/link that runs a script\n{{{\n<script label="click here">\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\n}}}\n<script label="click here">\n if (!window.story) window.story=window;\n alert("Hello World!\snlinktext='"+place.firstChild.data+"'\sntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");\n</script>\n\nloading a script from a source url\n{{{\n<script src="demo.js">return "loading demo.js..."</script>\n<script>return window.demo()</script>\n}}}\nwhere http://www.elsdesign.com/tiddlywiki/demo.js contains:\n>^^window.demo = function()^^\n>^^ { return 'this output is from demo(), defined in demo.js'; }^^\n>^^alert('InlineJavascriptPlugin: demo.js has been loaded');^^\n<script src="demo.js">return "loading demo.js..."</script>\n<script>return demo()</script>\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.01.05 [1.4.0]''\nadded support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.\n''2005.12.13 [1.3.1]''\nwhen catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski\n''2005.11.09 [1.3.0]''\nfor 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content\nBased on a suggestion by BradleyMeck\n''2005.11.08 [1.2.0]''\nhandle loading of javascript from an external URL via src="..." syntax\n''2005.11.08 [1.1.0]''\npass 'place' param into scripts to provide direct DOM access \n''2005.11.08 [1.0.0]''\ninitial release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.inlineJavascript= {major: 1, minor: 4, revision: 0, date: new Date(2006,1,5)};\n\nconfig.formatters.push( {\n name: "inlineJavascript",\n match: "\s\s<script",\n lookahead: "\s\s<script(?: src=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?(?: label=\s\s\s"((?:.|\s\sn)*?)\s\s\s")?\s\s>((?:.|\s\sn)*?)\s\s</script\s\s>",\n\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n if (lookaheadMatch[1]) { // load a script library\n // make script tag, set src, add to body to execute, then remove for cleanup\n var script = document.createElement("script"); script.src = lookaheadMatch[1];\n document.body.appendChild(script); document.body.removeChild(script);\n }\n if (lookaheadMatch[2] && lookaheadMatch[3]) { // create a link to an 'onclick' script\n // add a link, define click handler, save code in link (pass 'place'), set link attributes\n var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);\n link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}\n link.code="function _out(place){"+lookaheadMatch[3]+"};_out(this);"\n link.setAttribute("href","javascript:;"); link.setAttribute("title",""); link.style.cursor="pointer";\n }\n else if (lookaheadMatch[3]) { // run inline script code\n var code="function _out(place){"+lookaheadMatch[3]+"};_out(w.output);"\n code=code.replace(/document.write\s(/gi,'place.innerHTML+=(');\n try { var out = eval(code); } catch(e) { out = e.description?e.description:e.toString(); }\n if (out && out.length) wikify(out,w.output);\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n} )\n//}}}\n
/***\n|''Name:''|~IntelliTaggerPlugin|\n|''Version:''|1.0.0 (2006-04-26)|\n|''Type:''|plugin|\n|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|\n|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|\n|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|\n|''Source Code:''|[[IntelliTaggerPlugin SourceCode]]|\n|''Licence:''|[[BSD open source license (abego Software)]]|\n|''~TiddlyWiki:''|Version 2.0.8 or better|\n|''Browser:''|Firefox 1.5.0.2 or better|\n\n***/\n// /%\nif(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:0,date:new Date(2006,3,26),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.isPopupOpen=function(_2){return _2&&_2.parentNode==document.body;};abego.openAsPopup=function(_3){if(_3.parentNode!=document.body){document.body.appendChild(_3);}};abego.closePopup=function(_4){if(abego.isPopupOpen(_4)){document.body.removeChild(_4);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_5,_6,_7){_5.style.left=_6+"px";_5.style.top=_7+"px";};abego.centerOnWindow=function(_8){if(_8.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _9=abego.getWindowRect();abego.moveElement(_8,_9.left+(_9.width-_8.offsetWidth)/2,_9.top+(_9.height-_8.offsetHeight)/2);};abego.isDescendantOrSelf=function(_a,e){while(e){if(_a==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_c){var _d={};for(var i=0;i<_c.length;i++){_d[_c[i]]=true;}return _d;};abego.filterStrings=function(_f,_10,_11){var _12=[];for(var i=0;i<_f.length&&(_11===undefined||_12.length<_11);i++){var s=_f[i];if(s.match(_10)){_12.push(s);}}return _12;};abego.arraysAreEqual=function(a,b){var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_19,_1a){if(!_1a){return;}var _1b=findPosX(_1a);var _1c=findPosY(_1a);var _1d=_1a.offsetHeight;var _1e=_1b;var _1f=_1c+_1d;var _20=findWindowWidth();if(_20<_19.offsetWidth){_19.style.width=(_20-100)+"px";}var _21=_19.offsetWidth;if(_1e+_21>_20){_1e=_20-_21-30;}if(_1e<0){_1e=0;}_19.style.left=_1e+"px";_19.style.top=_1f+"px";_19.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _25=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_25.push([s.toString().toLowerCase(),s]);}_25.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_25[i][1];}};abego.getTiddlerField=function(_2b,_2c,_2d){var _2e=document.getElementById(_2b.idPrefix+_2c);var e=null;if(_2e!=null){var _30=_2e.getElementsByTagName("*");for(var t=0;t<_30.length;t++){var c=_30[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2d){e=c;}}}}return e;};abego.setRange=function(_33,_34,end){if(_33.setSelectionRange){_33.setSelectionRange(_34,end);var max=0+_33.scrollHeight;var len=_33.textLength;var top=max*_34/len,bot=max*end/len;_33.scrollTop=Math.min(top,(bot+top-_33.clientHeight)/2);}else{if(_33.createTextRange!=undefined){var _39=_33.createTextRange();_39.collapse();_39.moveEnd("character",end);_39.moveStart("character",_34);_39.select();}else{_33.select();}}};abego.internal.TagManager=function(){var _3a=null;var _3b=function(){if(_3a){return;}_3a={};store.forEachTiddler(function(_3c,_3d){for(var i=0;i<_3d.tags.length;i++){var tag=_3d.tags[i];var _40=_3a[tag];if(!_40){_40=_3a[tag]={count:0,tiddlers:{}};}_40.tiddlers[_3d.title]=true;_40.count+=1;}});};var _41=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_42,_43,_44,_45,_46,_47){var _48=this.fetchTiddler(_42);var _49=_48?_48.tags:[];var _4a=(typeof _47=="string")?_47.readBracketedList():_47;_41.apply(this,arguments);if(!abego.arraysAreEqual(_49,_4a)){abego.internal.getTagManager().reset();}};var _4b=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4c){var _4d=this.fetchTiddler(_4c);var _4e=_4d&&_4d.tags.length>0;_4b.apply(this,arguments);if(_4e){abego.internal.getTagManager().reset();}};this.reset=function(){_3a=null;};this.getTiddlersWithTag=function(tag){_3b();var _50=_3a[tag];return _50?_50.tiddlers:null;};this.getAllTags=function(_51){_3b();var _52=[];for(var i in _3a){_52.push(i);}for(i=0;_51&&i<_51.length;i++){_52.pushUnique(_51[i],true);}abego.sortIgnoreCase(_52);return _52;};this.getTagInfos=function(){_3b();var _54=[];for(var _55 in _3a){_54.push([_55,_3a[_55]]);}return _54;};var _56=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3b();var _5c=this.getTagInfos();_5c.sort(_56);return _5c;};this.getPartnerRankedTags=function(_5d){var _5e={};for(var i=0;i<_5d.length;i++){var _60=this.getTiddlersWithTag(_5d[i]);for(var _61 in _60){var _62=store.getTiddler(_61);if(!(_62 instanceof Tiddler)){continue;}for(var j=0;j<_62.tags.length;j++){var tag=_62.tags[j];var c=_5e[tag];_5e[tag]=c?c+1:1;}}}var _66=abego.toSet(_5d);var _67=[];for(var n in _5e){if(!_66[n]){_67.push(n);}}_67.sort(function(a,b){var d=_5e[b]-_5e[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _67;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6c=2;var _6d=1;var _6e=30;var _6f;var _70;var _71;var _72;var _73;var _74;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _75=function(){return _70;};var _76=function(tag){return _73[tag];};var _78=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7b=function(_7c){var s=_7c.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _7f=function(_80){var s=_80.value;var len=s.length;if(len>0&&s[len-1]!=" "){_80.value+=" ";}};var _83=function(tag,_85,_86){if(_7b(_85)){_85.value=_78(_85.value);}story.setTiddlerTag(_86.title,tag,0);_7f(_85);abego.IntelliTagger.assistTagging(_85,_86);};var _87=function(n){if(_74){if(_74.length>n){return _74[n];}n-=_74.length;}return (_72&&_72.length>n)?_72[n]:null;};var _89=function(n,_8b,_8c){var _8d=_87(n);if(_8d){_83(_8d,_8b,_8c);}};var _8e=function(_8f){var pos=_8f.value.lastIndexOf(" ");var _91=(pos>=0)?_8f.value.substr(++pos,_8f.value.length):_8f.value;return new RegExp(_91.escapeRegExp(),"i");};var _92=function(_93,_94){var _95=0;for(var i=0;i<_93.length;i++){if(_94[_93[i]]){_95++;}}return _95;};var _97=function(_98,_99,_9a){var _9b=1;var c=_98[_99];for(var i=_99+1;i<_98.length;i++){if(_98[i][1].count==c){if(_98[i][0].match(_9a)){_9b++;}}else{break;}}return _9b;};var _9e=function(_9f,_a0){var _a1=abego.internal.getTagManager().getSortedTagInfos();var _a2=[];var _a3=0;for(var i=0;i<_a1.length;i++){var c=_a1[i][1].count;if(c!=_a3){if(_a0&&(_a2.length+_97(_a1,i,_9f)>_a0)){break;}_a3=c;}if(c==1){break;}var s=_a1[i][0];if(s.match(_9f)){_a2.push(s);}}return _a2;};var _a7=function(_a8,_a9){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_a9),_a8);};var _aa=function(){if(!_6f){return;}var _ab=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ab){_ab="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_6f.innerHTML=_ab;applyHtmlMacros(_6f,null);refreshElements(_6f,null);};var _ac=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_71){_71.call(this,tag,e);}return false;};var _af=function(_b0,_b1,_b2,_b3){if(!_b1){return;}var _b4=_b3?abego.toSet(_b3):{};var n=_b1.length;for(var i=0;i<n;i++){var tag=_b1[i];if(_b4[tag]){continue;}if(i>0){createTiddlyElement(_b0,"span",null,"tagSeparator"," | ");}var _b8="";var _b9=_b0;if(_b2<10){_b9=createTiddlyElement(_b0,"span",null,"numberedSuggestion");_b2++;var key=_b2<10?""+(_b2):"0";createTiddlyElement(_b9,"span",null,"suggestionNumber",key+") ");var _bb=_b2==1?"Ctrl-Space or ":"";_b8=" (Shortcut: %1Alt-%0)".format([key,_bb]);}var _bc=config.views.wikified.tag.tooltip.format([tag]);var _bd=(_76(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_b8]);var _be="%0; Shift-Click: %1".format([_bd,_bc]);var btn=createTiddlyButton(_b9,tag,_be,_ac,_76(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c0=function(){if(_6f){window.scrollTo(0,ensureVisible(_6f));}if(_75()){window.scrollTo(0,ensureVisible(_75()));}};var _c1=function(e){if(!e){var e=window.event;}if(!_6f){return;}var _c3=resolveTarget(e);if(_c3==_75()){return;}if(abego.isDescendantOrSelf(_6f,_c3)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c1);var _c4=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_c6){_c4.apply(this,arguments);var _c7=_c6.tags;if(_c7){_c6.tags=_c7.trim();}};var _c8=function(_c9){story.focusTiddler(_c9,"tags");var _ca=abego.getTiddlerField(story,_c9,"tags");if(_ca){var len=_ca.value.length;abego.setRange(_ca,len,len);window.scrollTo(0,ensureVisible(_ca));}};var _cc=config.macros.edit.handler;config.macros.edit.handler=function(_cd,_ce,_cf,_d0,_d1,_d2){_cc.apply(this,arguments);var _d3=_cf[0];if((_d2 instanceof Tiddler)&&_d3=="tags"){var _d4=_cd.lastChild;_d4.onfocus=function(e){abego.IntelliTagger.assistTagging(_d4,_d2);setTimeout(function(){_c8(_d2.title);},100);};_d4.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_89(e.keyCode==48?9:e.keyCode-49,_d4,_d2);}else{if(e.ctrlKey&&e.keyCode==32){_89(0,_d4,_d2);}}setTimeout(function(){abego.IntelliTagger.assistTagging(_d4,_d2);},100);return false;};_7f(_d4);}};var _d7=function(e){if(!e){var e=window.event;}var _d9=resolveTarget(e);var _da=_d9.getAttribute("tiddler");if(_da){story.displayTiddler(_d9,_da,"IntelliTaggerEditTagsTemplate",false);_c8(_da);}return false;};var _db=config.macros.tags.handler;config.macros.tags.handler=function(_dc,_dd,_de,_df,_e0,_e1){_db.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_e1,createTiddlyElement(_dc.lastChild,"li"));};var _e2=function(){if(_6f&&_70&&!abego.isDescendantOrSelf(document,_70)){abego.IntelliTagger.close();}};setInterval(_e2,100);abego.IntelliTagger.displayTagSuggestions=function(_e3,_e4,_e5,_e6,_e7){_72=_e3;_73=abego.toSet(_e4);_74=_e5;_70=_e6;_71=_e7;if(!_6f){_6f=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_6f.style.position="absolute";}_aa();abego.openAsPopup(_6f);if(_75()){var w=_75().offsetWidth;if(_6f.offsetWidth<w){_6f.style.width=(w-2*(_6c+_6d))+"px";}abego.moveBelowAndClip(_6f,_75());}else{abego.centerOnWindow(_6f);}_c0();};abego.IntelliTagger.assistTagging=function(_e9,_ea){var _eb=_8e(_e9);var s=_e9.value;if(_7b(_e9)){s=_78(s);}var _ed=s.readBracketedList();var _ee=_ed.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_ed),_eb,_6e):_9e(_eb,_6e);abego.IntelliTagger.displayTagSuggestions(_a7(_eb,_ed),_ed,_ee,_e9,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_83(tag,_e9,_ea);}});};abego.IntelliTagger.close=function(){abego.closePopup(_6f);_6f=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_f1,_f2,_f3,_f4,_f5,id,_f7){if(!_f3){_f3="[edit]";}if(!_f4){_f4="Edit the tags";}if(!_f5){_f5="editTags";}var _f8=createTiddlyButton(_f2,_f3,_f4,_d7,_f5,id,_f7);_f8.setAttribute("tiddler",(_f1 instanceof Tiddler)?_f1.title:String(_f1));return _f8;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_f9,_fa,_fb,_fc,_fd,_fe){var _ff=_fd.parseParams("list",null,true);var _100=_ff[0]["action"];for(var i=0;_100&&i<_100.length;i++){var _102=_100[i];var _103=config.macros.intelliTagger.subhandlers[_102];if(!_103){abego.alertAndThrow("Unsupported action '%0'".format([_102]));}_103(_f9,_fa,_fb,_fc,_fd,_fe);}},subhandlers:{showTags:function(_104,_105,_106,_107,_108,_109){_af(_104,_72,_74?_74.length:0,_74);},showFavorites:function(_10a,_10b,_10c,_10d,_10e,_10f){_af(_10a,_74,0);},closeButton:function(_110,_111,_112,_113,_114,_115){var _116=createTiddlyButton(_110,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_117){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_117,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">"+t+"<font>";},copyright:function(_11a){var e=createTiddlyElement(_11a,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">© 2006 <b><font color=\s"red\s">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\sn"+"!~IntelliTagger Stylesheet\sn"+"***/\sn"+"/*{{{*/\sn"+".intelliTaggerSuggestions {\sn"+"\stposition: absolute;\sn"+"\stwidth: 600px;\sn"+"\sn"+"\stpadding: 2px;\sn"+"\stlist-style: none;\sn"+"\stmargin: 0;\sn"+"\sn"+"\stbackground: #eeeeee;\sn"+"\stborder: 1px solid DarkGray;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .currentTag {\sn"+"\stfont-weight: bold;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .suggestionNumber {\sn"+"\stcolor: #808080;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .numberedSuggestion{\sn"+"\stwhite-space: nowrap;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .intelliTaggerFooter {\sn"+"\stmargin-top: 4px;\sn"+"\stborder-top-width: thin;\sn"+"\stborder-top-style: solid;\sn"+"\stborder-top-color: #999999;\sn"+"}\sn"+".intelliTaggerSuggestions .favorites {\sn"+"\stborder-bottom-width: thin;\sn"+"\stborder-bottom-style: solid;\sn"+"\stborder-bottom-color: #999999;\sn"+"\stpadding-bottom: 2px;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .normalTags {\sn"+"\stpadding-top: 2px;\sn"+"}\sn"+"\sn"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\sn"+"\stfont-size: 10px;\sn"+"\sn"+"\stpadding-left: 0.3em;\sn"+"\stpadding-right: 0.3em;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<div class=\s"favorites\s" macro=\s"intelliTagger action: showFavorites\s"></div>\sn"+"<div class=\s"normalTags\s" macro=\s"intelliTagger action: showTags\s"></div>\sn"+"<!-- The Footer (with the Navigation) ============================================ -->\sn"+"<table class=\s"intelliTaggerFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\st<span macro=\s"intelliTagger action: closeButton\s"></span>\sn"+"\st</td>\sn"+"\st<td align=\s"right\s">\sn"+"\st\st<span macro=\s"intelliTagger action: version\s"></span>, <span macro=\s"intelliTagger action: copyright \s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"<!--\sn"+"}}}\sn"+"-->\sn";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\sn"+"<div class='title' macro='view title'></div>\sn"+"<div class='tagged' macro='tags'></div>\sn"+"<div class='viewer' macro='view text wikified'></div>\sn"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\sn"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\sn"+"<!--\sn"+"}}}\sn"+"-->\sn";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/src/Plugin-IntelliTagger-src.js]]";setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"intelliTagger");}\n//%/\n
Derived from [[this|http://www.squarefree.com/shell/?ignoreReferrerFrom=shell1.4]]\nstore.fetchTiddler("Test").revisionKey\ntime(f, n)\n<html>\n<div>\n Features: autocompletion of property names with Tab, multiline input with Shift+Enter, input history with (Ctrl+) Up/Down, \n <a accesskey="M" href="javascript:jsshell.go('scope(Math); mathHelp();');" title="Accesskey: M">Math</a>\n</div>\n<div>\nValues and functions: ans, print(string), \n <a accesskey="P" href="javascript:jsshell.go('props(ans)')" title="Accesskey: P">props(object)</a>, \n <a accesskey="B" href="javascript:jsshell.go('blink(ans)')" title="Accesskey: B">blink(node)</a>, \n <a href="javascript:jsshell.go('wikify(ans)')">wikify(text)</a>\n <a href="javascript:jsshell.go('print(ans)')">print(text)</a>\n <a accesskey="C" href="javascript:jsshell.go('clear()')" title="Accesskey: C">clear()</a>, \n load(scriptURL), \n scope(object)</div>\n<div class="shell">\n <div id="output"></div>\n <div><textarea id="input" class="input" wrap="off" onkeydown="jsshell.inputKeydown(event)" rows="1"></textarea></div>\n</div>\n</html><script>\nwindow.jsshell = {}; // Put our functions in the global namespace.\n\nwindow.jsshell.refocus = function()\n{\n jsshell._in.blur(); // Needed for Mozilla to scroll correctly.\n jsshell._in.focus();\n}\n\nwindow.jsshell.initTarget = function()\n{\n window.print = jsshell.shellCommands.print;\n}\n\n// Unless the user is selected something, refocus the textbox.\n// (requested by caillon, brendan, asa)\nwindow.jsshell.keepFocusInTextbox = function(e) \n{\n var g = e.srcElement ? e.srcElement : e.target; // IE vs. standard\n \n while (!g.tagName)\n g = g.parentNode;\n var t = g.tagName.toUpperCase();\n if (t=="A" || t=="INPUT")\n return;\n \n if (window.getSelection) {\n // Mozilla\n if (String(window.getSelection()))\n return;\n }\n else if (document.getSelection) {\n // Opera? Netscape 4?\n if (document.getSelection())\n return;\n }\n else {\n // IE\n if ( document.selection.createRange().text )\n return;\n }\n \n jsshell.refocus();\n}\n\n//function inputKeydown(e) {\nwindow.jsshell.inputKeydown = function(e) {\n // Use onkeydown because IE doesn't support onkeypress for arrow keys\n\n //alert(e.keyCode + " ^ " + e.keycode);\n\n if (e.shiftKey && e.keyCode == 13) { // shift-enter\n // don't do anything; allow the shift-enter to insert a line break as normal\n } else if (e.keyCode == 13) { // enter\n // execute the input on enter\n try { jsshell.go(); } catch(er) { alert(er); };\n setTimeout(function() { jsshell._in.value = ""; }, 0); // can't preventDefault on input, so clear it later\n } else if (e.keyCode == 38) { // up\n // go up in history if at top or ctrl-up\n if (e.ctrlKey || jsshell.caretInFirstLine(jsshell._in))\n jsshell.hist(true);\n } else if (e.keyCode == 40) { // down\n // go down in history if at end or ctrl-down\n if (e.ctrlKey || jsshell.caretInLastLine(jsshell._in))\n jsshell.hist(false);\n } else if (e.keyCode == 9) { // tab\n jsshell.tabcomplete();\n setTimeout(function() { jsshell.refocus(); }, 0); // refocus because tab was hit\n } else { }\n\n setTimeout(jsshell.recalculateInputHeight, 0);\n \n //return true;\n};\n\nwindow.jsshell.caretInFirstLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionStart == undefined)\n return true;\n\n var firstLineBreak = textbox.value.indexOf("\sn");\n\n return ((firstLineBreak == -1) || (textbox.selectionStart <= firstLineBreak));\n}\n\nwindow.jsshell.caretInLastLine = function(textbox)\n{\n // IE doesn't support selectionStart/selectionEnd\n if (textbox.selectionEnd == undefined)\n return true;\n\n var lastLineBreak = textbox.value.lastIndexOf("\sn");\n \n return (textbox.selectionEnd > lastLineBreak);\n}\n\nwindow.jsshell.recalculateInputHeight = function()\n{\n var rows = jsshell._in.value.split(/\sn/).length\n + 1 // prevent scrollbar flickering in Mozilla\n + (window.opera ? 1 : 0); // leave room for scrollbar in Opera\n\n if (jsshell._in.rows != rows) // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0.\n jsshell._in.rows = rows;\n}\n\nwindow.jsshell.println = function(s, type)\n{\n if((s=String(s)))\n {\n var newdiv = document.createElement("div");\n newdiv.appendChild(document.createTextNode(s));\n newdiv.className = type;\n jsshell._out.appendChild(newdiv);\n return newdiv;\n }\n}\n\nwindow.jsshell.printWithRunin = function(h, s, type)\n{\n var div = jsshell.println(s, type);\n var head = document.createElement("strong");\n head.appendChild(document.createTextNode(h + ": "));\n div.insertBefore(head, div.firstChild);\n}\n\nwindow.jsshell.shellCommands = \n{\nload : function load(url)\n{\n var s = document.createElement("script");\n s.type = "text/javascript";\n s.src = url;\n document.getElementsByTagName("head")[0].appendChild(s);\n jsshell.println("Loading " + url + "...", "message");\n},\n\nclear : function clear()\n{\n jsshell._out.innerHTML = "";\n},\n\nwikify : function wikify(text)\n{\n window.wikify(text, jsshell._out);\n},\n\nprint : function print(s) { jsshell.println(s, "print"); },\n\n// the normal function, "print", shouldn't return a value\n// (suggested by brendan; later noticed it was a problem when showing others)\npr : function pr(s) \n{ \n jsshell.shellCommands.print(s); // need to specify shellCommands so it doesn't try window.print()!\n return s;\n},\n\nprops : function props(e, onePerLine)\n{\n if (e === null) {\n jsshell.println("props called with null argument", "error");\n return;\n }\n\n if (e === undefined) {\n jsshell.println("props called with undefined argument", "error");\n return;\n }\n\n var ns = ["Methods", "Fields", "Unreachables"];\n var as = [[], [], []]; // array of (empty) arrays of arrays!\n var p, j, i; // loop variables, several used multiple times\n\n var protoLevels = 0;\n\n for (p = e; p; p = p.__proto__)\n {\n for (i=0; i<ns.length; ++i)\n as[i][protoLevels] = [];\n ++protoLevels;\n }\n\n for(var a in e)\n {\n // Shortcoming: doesn't check that VALUES are the same in object and prototype.\n\n var protoLevel = -1;\n try\n {\n for (p = e; p && (a in p); p = p.__proto__)\n ++protoLevel;\n }\n catch(er) { protoLevel = 0; } // "in" operator throws when param to props() is a string\n\n var type = 1;\n try\n {\n if ((typeof e[a]) == "function")\n type = 0;\n }\n catch (er) { type = 2; }\n\n as[type][protoLevel].push(a);\n }\n\n function times(s, n) { return n ? s + times(s, n-1) : ""; }\n\n for (j=0; j<protoLevels; ++j)\n for (i=0;i<ns.length;++i)\n if (as[i][j].length) \n jsshell.printWithRunin(\n ns[i] + times(" of prototype", j), \n (onePerLine ? "\sn\sn" : "") + as[i][j].sort().join(onePerLine ? "\sn" : ", ") + (onePerLine ? "\sn\sn" : ""), \n "propList"\n );\n},\n\nblink : function blink(node)\n{\n if (!node) throw("blink: argument is null or undefined.");\n if (node.nodeType == null) throw("blink: argument must be a node.");\n if (node.nodeType == 3) throw("blink: argument must not be a text node");\n if (node.documentElement) throw("blink: argument must not be the document object");\n\n function setOutline(o) { \n return function() {\n if (node.style.outline != node.style.bogusProperty) {\n // browser supports outline (Firefox 1.1 and newer, CSS3, Opera 8).\n node.style.outline = o;\n }\n else if (node.style.MozOutline != node.style.bogusProperty) {\n // browser supports MozOutline (Firefox 1.0.x and older)\n node.style.MozOutline = o;\n }\n else {\n // browser only supports border (IE). border is a fallback because it moves things around.\n node.style.border = o;\n }\n }\n } \n \n function focusIt(a) {\n return function() {\n a.focus(); \n }\n }\n\n if (node.ownerDocument) {\n var windowToFocusNow = (node.ownerDocument.defaultView || node.ownerDocument.parentWindow); // Moz vs. IE\n if (windowToFocusNow)\n setTimeout(focusIt(windowToFocusNow.top), 0);\n }\n\n for(var i=1;i<7;++i)\n setTimeout(setOutline((i%2)?'3px solid red':'none'), i*100);\n\n setTimeout(focusIt(window), 800);\n setTimeout(focusIt(jsshell._in), 810);\n},\n\ntime: function (f, n) { \n var start = new Date(); \n if (typeof n != typeof undefined) { \n for (var i = 0; i < n; i++) { f(); } } \n else { f(); } \n var stop = new Date(); \n return stop - start; \n},\n\nscope : function scope(sc)\n{\n if (!sc) sc = {};\n jsshell._scope = sc;\n jsshell.println("Scope is now " + sc + ". If a variable is not found in this scope, window will also be searched. New variables will still go on window.", "message");\n},\n\nmathHelp : function mathHelp()\n{\n jsshell.printWithRunin("Math constants", "E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2", "propList");\n jsshell.printWithRunin("Math methods", "abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan", "propList");\n},\n\nans : undefined\n};\n\n\nwindow.jsshell.hist = function(up)\n{\n // histList[0] = first command entered, [1] = second, etc.\n // type something, press up --> thing typed is now in "limbo"\n // (last item in histList) and should be reachable by pressing \n // down again.\n\n var L = jsshell.histList.length;\n\n if (L == 1)\n return;\n\n if (up)\n {\n if (jsshell.histPos == L-1)\n {\n // Save this entry in case the user hits the down key.\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n }\n\n if (jsshell.histPos > 0)\n {\n jsshell.histPos--;\n // Use a timeout to prevent up from moving cursor within new text\n // Set to nothing first for the same reason\n setTimeout(\n function() {\n jsshell._in.value = ''; \n jsshell._in.value = jsshell.histList[jsshell.histPos];\n var caretPos = jsshell._in.value.length;\n if (jsshell._in.setSelectionRange) \n jsshell._in.setSelectionRange(caretPos, caretPos);\n },\n 0\n );\n }\n } \n else // down\n {\n if (jsshell.histPos < L-1)\n {\n jsshell.histPos++;\n jsshell._in.value = jsshell.histList[jsshell.histPos];\n }\n else if (jsshell.histPos == L-1)\n {\n // Already on the current entry: clear but save\n if (jsshell._in.value)\n {\n jsshell.histList[jsshell.histPos] = jsshell._in.value;\n ++jsshell.histPos;\n jsshell._in.value = "";\n }\n }\n }\n}\n\nwindow.jsshell.tabcomplete = function()\n{\n /*\n * Working backwards from s[from], find the spot\n * where this expression starts. It will scan\n * until it hits a mismatched ( or a space,\n * but it skips over quoted strings.\n * If stopAtDot is true, stop at a '.'\n */\n function findbeginning(s, from, stopAtDot)\n {\n /*\n * Complicated function.\n *\n * Return true if s[i] == q BUT ONLY IF\n * s[i-1] is not a backslash.\n */\n function equalButNotEscaped(s,i,q)\n {\n if(s.charAt(i) != q) // not equal go no further\n return false;\n\n if(i==0) // beginning of string\n return true;\n\n if(s.charAt(i-1) == '\s\s') // escaped?\n return false;\n\n return true;\n }\n\n var nparens = 0;\n var i;\n for(i=from; i>=0; i--)\n {\n if(s.charAt(i) == ' ')\n break;\n\n if(stopAtDot && s.charAt(i) == '.')\n break;\n \n if(s.charAt(i) == ')')\n nparens++;\n else if(s.charAt(i) == '(')\n nparens--;\n\n if(nparens < 0)\n break;\n\n // skip quoted strings\n if(s.charAt(i) == '\s'' || s.charAt(i) == '\s"')\n {\n //dump("skipping quoted chars: ");\n var quot = s.charAt(i);\n i--;\n while(i >= 0 && !equalButNotEscaped(s,i,quot)) {\n //dump(s.charAt(i));\n i--;\n }\n //dump("\sn");\n }\n }\n return i;\n }\n\n // XXX should be used more consistently (instead of using selectionStart/selectionEnd throughout code)\n // XXX doesn't work in IE, even though it contains IE-specific code\n function getcaretpos(inp)\n {\n if(inp.selectionEnd != null)\n return inp.selectionEnd;\n \n if(inp.createTextRange)\n {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n if (inprange.setEndPoint)\n {\n inprange.setEndPoint('EndToStart', docrange);\n return inprange.text.length;\n }\n }\n\n return inp.value.length; // sucks, punt\n }\n\n function setselectionto(inp,pos)\n {\n if(inp.selectionStart) {\n inp.selectionStart = inp.selectionEnd = pos;\n }\n else if(inp.createTextRange) {\n var docrange = document.selection.createRange();\n var inprange = inp.createTextRange();\n inprange.move('character',pos);\n inprange.select();\n }\n else { // err...\n /*\n inp.select();\n if(document.getSelection())\n document.getSelection() = "";\n */\n }\n }\n // get position of cursor within the input box\n var caret = getcaretpos(jsshell._in);\n\n if(caret) {\n //dump("----\sn");\n var dotpos, spacepos, complete, obj;\n //dump("caret pos: " + caret + "\sn");\n // see if there's a dot before here\n dotpos = findbeginning(jsshell._in.value, caret-1, true);\n //dump("dot pos: " + dotpos + "\sn");\n if(dotpos == -1 || jsshell._in.value.charAt(dotpos) != '.') {\n dotpos = caret;\n//dump("changed dot pos: " + dotpos + "\sn");\n }\n\n // look backwards for a non-variable-name character\n spacepos = findbeginning(jsshell._in.value, dotpos-1, false);\n //dump("space pos: " + spacepos + "\sn");\n // get the object we're trying to complete on\n if(spacepos == dotpos || spacepos+1 == dotpos || dotpos == caret)\n {\n // try completing function args\n if(jsshell._in.value.charAt(dotpos) == '(' ||\n (jsshell._in.value.charAt(spacepos) == '(' && (spacepos+1) == dotpos))\n {\n var fn,fname;\n var from = (jsshell._in.value.charAt(dotpos) == '(') ? dotpos : spacepos;\n spacepos = findbeginning(jsshell._in.value, from-1, false);\n\n fname = jsshell._in.value.substr(spacepos+1,from-(spacepos+1));\n //dump("fname: " + fname + "\sn");\n try {\n with(window)\n with(jsshell._scope)\n with(jsshell.shellCommands)\n fn = eval(fname);\n }\n catch(er) {\n //dump('fn is not a valid object\sn');\n return;\n }\n if(fn == undefined) {\n //dump('fn is undefined');\n return;\n }\n if(fn instanceof Function)\n {\n // Print function definition, including argument names, but not function body\n if(!fn.toString().match(/function .+?\s(\s) +\s{\sn +\s[native code\s]\sn\s}/))\n jsshell.println(fn.toString().match(/function .+?\s(.*?\s)/), "tabcomplete");\n }\n\n return;\n }\n else\n obj = window;\n }\n else\n {\n var objname = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n //dump("objname: |" + objname + "|\sn");\n try {\n with(jsshell._scope)\n with(window)\n obj = eval(objname);\n }\n catch(er) {\n jsshell.printError(er); \n return;\n }\n if(obj == undefined) {\n // sometimes this is tabcomplete's fault, so don't print it :(\n // e.g. completing from "print(document.getElements"\n // jsshell.println("Can't complete from null or undefined expression " + objname, "error");\n return;\n }\n }\n //dump("obj: " + obj + "\sn");\n // get the thing we're trying to complete\n if(dotpos == caret)\n {\n if(spacepos+1 == dotpos || spacepos == dotpos)\n {\n // nothing to complete\n //dump("nothing to complete\sn");\n return;\n }\n\n complete = jsshell._in.value.substr(spacepos+1,dotpos-(spacepos+1));\n }\n else {\n complete = jsshell._in.value.substr(dotpos+1,caret-(dotpos+1));\n }\n //dump("complete: " + complete + "\sn");\n // ok, now look at all the props/methods of this obj\n // and find ones starting with 'complete'\n var matches = [];\n var bestmatch = null;\n for(var a in obj)\n {\n //a = a.toString();\n //XXX: making it lowercase could help some cases,\n // but screws up my general logic.\n if(a.substr(0,complete.length) == complete) {\n matches.push(a);\n ////dump("match: " + a + "\sn");\n // if no best match, this is the best match\n if(bestmatch == null)\n {\n bestmatch = a;\n }\n else {\n // the best match is the longest common string\n function min(a,b){ return ((a<b)?a:b); }\n var i;\n for(i=0; i< min(bestmatch.length, a.length); i++)\n {\n if(bestmatch.charAt(i) != a.charAt(i))\n break;\n }\n bestmatch = bestmatch.substr(0,i);\n ////dump("bestmatch len: " + i + "\sn");\n }\n ////dump("bestmatch: " + bestmatch + "\sn");\n }\n }\n bestmatch = (bestmatch || "");\n ////dump("matches: " + matches + "\sn");\n var objAndComplete = (objname || obj) + "." + bestmatch;\n //dump("matches.length: " + matches.length + ", jsshell.tooManyMatches: " + jsshell.tooManyMatches + ", objAndComplete: " + objAndComplete + "\sn");\n if(matches.length > 1 && (jsshell.tooManyMatches == objAndComplete || matches.length <= 10)) {\n\n jsshell.printWithRunin("Matches: ", matches.join(', '), "tabcomplete");\n jsshell.tooManyMatches = null;\n }\n else if(matches.length > 10)\n {\n jsshell.println(matches.length + " matches. Press tab again to see them all", "tabcomplete");\n jsshell.tooManyMatches = objAndComplete;\n }\n else {\n jsshell.tooManyMatches = null;\n }\n if(bestmatch != "")\n {\n var sstart;\n if(dotpos == caret) {\n sstart = spacepos+1;\n }\n else {\n sstart = dotpos+1;\n }\n jsshell._in.value = jsshell._in.value.substr(0, sstart)\n + bestmatch\n + jsshell._in.value.substr(caret);\n setselectionto(jsshell._in,caret + (bestmatch.length - complete.length));\n }\n }\n}\n\nwindow.jsshell.printQuestion = function(q)\n{\n jsshell.println(q, "input");\n}\n\nwindow.jsshell.printAnswer = function(a)\n{\n if (a !== undefined) {\n jsshell.println(a, "normalOutput");\n jsshell.shellCommands.ans = a;\n }\n}\n\nwindow.jsshell.printError = function(er)\n{ \n var lineNumberString;\n\n lastError = er; // for debugging the shell\n if (er.name)\n {\n // lineNumberString should not be "", to avoid a very wacky bug in IE 6.\n lineNumberString = (er.lineNumber != undefined) ? (" on line " + er.lineNumber + ": ") : ": ";\n jsshell.println(er.name + lineNumberString + er.message, "error"); // Because IE doesn't have error.toString.\n }\n else\n jsshell.println(er, "error"); // Because security errors in Moz /only/ have toString.\n}\n\nwindow.jsshell.go = function(s)\n{\n jsshell._in.value = jsshell.question = s ? s : jsshell._in.value;\n\n if (jsshell.question == "")\n return;\n\n jsshell.histList[jsshell.histList.length-1] = jsshell.question;\n jsshell.histList[jsshell.histList.length] = "";\n jsshell.histPos = jsshell.histList.length - 1;\n \n // Unfortunately, this has to happen *before* the JavaScript is run, so that \n // print() output will go in the right place.\n jsshell._in.value='';\n jsshell.recalculateInputHeight();\n jsshell.printQuestion(jsshell.question);\n\n if (window.closed) {\n jsshell.printError("Target window has been closed.");\n return;\n }\n \n try { ("jsshell" in window) }\n catch(er) {\n jsshell.printError("The JavaScript Shell cannot access variables in the target window. The most likely reason is that the target window now has a different page loaded and that page has a different hostname than the original page.");\n return;\n }\n\n if (!("jsshell" in window))\n initTarget(); // silent\n\n // Evaluate Shell.question using _win's eval (this is why eval isn't in the |with|, IIRC).\n// window.location.href = "javascript:try{ jsshell.printAnswer(eval('with(jsshell._scope) with(jsshell.shellCommands) {' + jsshell.question + String.fromCharCode(10) + '}')); } catch(er) { jsshell.printError(er); }; setTimeout(jsshell.refocus, 0); void 0";\n try { \n jsshell.printAnswer(eval(\n 'with(jsshell._scope) with(jsshell.shellCommands) {' \n + jsshell.question + String.fromCharCode(10) + \n '}')); \n } catch(er) { \n jsshell.printError(er); \n }; \n setTimeout(jsshell.refocus, 0);\n}\n\nwindow.jsshell.histList = [""]; \nwindow.jsshell.histPos = 0; \nwindow.jsshell._scope = {}; \nwindow.jsshell.question;\nwindow.jsshell._in;\nwindow.jsshell._out;\nwindow.jsshell.tooManyMatches = null;\nwindow.jsshell.lastError = null;\n\njsshell._in = document.getElementById("input");\njsshell._out = document.getElementById("output");\n\njsshell.initTarget();\n\njsshell.recalculateInputHeight();\njsshell.refocus();\n\n</script>\n
[[KESI|http://sourceforge.net/projects/kesi]]\n[[KEmul - KDE Emulation module|http://sourceforge.net/projects/kemul]]\n[[KisoCD|http://sourceforge.net/projects/kisocd]]\n[[DVDAuthor Wizard|http://sourceforge.net/projects/dvdauthorwizard]]\n[[Boson|http://sourceforge.net/projects/boson]]
/***\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
# 0. Install required tools and libraries\n\nIf you have not installed RubyGems, Rake and Rails, you have to install them first.\n \nDownload RubyGems from http://rubyforge.org/frs/?group_id=126 and follow the setup instructions of it.\n\nExecute the following.\n\n % gem install rails --include-dependencies\n\nIf you have not installed a DB adapter for your DB, install it.\n \n#### MySQL:\n\n % gem install mysql\n \nIf the above command fails, try this.\n % gem install mysql -- --with-mysql-config\n \n#### PostgreSQL:\n \n % gem install postgres\n\nIf you want to use Markdown as a text formatting, you should install BlueCloth because RedCloth does not support Markdown sufficiently.\n\n % gem install bluecloth\n\n# 1. Unpack the zip in some directory.\n\n# 2. Create a database for LesserWiki\n\n#### MySQL:\n\n % mysql -u root\n mysql> create database lesserwiki default character set utf8;\n\n(You might have to specify password.)\n\n#### PostgreSQL:\n\n % createdb -E UNICODE lesserwiki\n\n(You might have to specify user and password.)\n\n# 3. Modify the config/database.yml to reflect your newly created database configuration\n\n# 4. Create tables in the database\n\nIf you are using MySQL or PostgreSQL.\n\n % rake db:migrate\n\nIf you are using another DB, try this.\n\n % rake db:schema:load\n\n# 5. Change owner and permissions of log and tmp directory\n\ntmp/cache, tmp/sockets, tmp/sessions and log directory must be writable for web server processes.\nYou should also consider the security.\n\n# 6. Rewrite ruby path of public/dispatch.* for your environment\n\n# 7. Run script/server -e production and see if it works \n\n# 8. Point your browser to http://localhost:3000/\n\n# 9. Create administrator account on the page\n\n# 10. Save the settings on the administration page\n\n# 11. Click "Go to Wiki" or go to http://localhost:3000/ again\n\nAfter the above works, We recommend to setup FastCGI or SCGI because of\nrendering performance.\n
{{{\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title.length' \n descending\n>>\n}}}\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title.length' \n descending\n>>\n\nSee also [[ForEachTiddlerExamples]].
{{{\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title.length' \n descending\n>>\n}}}\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title.length' \n descending\n>>
{{{\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title' \n descending\n>>\n}}}\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")' \n sortBy \n 'tiddler.title' \n descending\n>>\nSee also [[ForEachTiddlerExamples]].
{{{\n<<forEachTiddler \n where \n 'tiddler.tags.contains("systemConfig")'\n>>\n}}}\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.tags.contains("systemConfig")'\n>>\nSee also [[ForEachTiddlerExamples]].
{{{\n<<forEachTiddler \n where \n 'tiddler.title.startsWith("Site")' \n>> \n}}}\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.title.startsWith("Site")' \n>> \nSee also [[ForEachTiddlerExamples]].
{{{\n<<forEachTiddler\n where\n 'tiddler.tags && tiddler.tags.length'\n sortBy \n 'getSortedTagsText(tiddler)+"###"+tiddler.title'\n script\n 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function getGroupTitle(tiddler, context) {if (!context.lastGroup || context.lastGroup != getSortedTagsText(tiddler)) { context.lastGroup = getSortedTagsText(tiddler); return "* {{{"+(context.lastGroup?context.lastGroup:"no tags")+"}}}\sn";} else return "";} '\n write\n 'getGroupTitle(tiddler, context)+"** [[" + tiddler.title+"]]\sn"'\n>>\n}}}\n<<forEachTiddler\n where\n 'tiddler.tags && tiddler.tags.length'\n sortBy \n 'getSortedTagsText(tiddler)+"###"+tiddler.title'\n script\n 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function getGroupTitle(tiddler, context) {if (!context.lastGroup || context.lastGroup != getSortedTagsText(tiddler)) { context.lastGroup = getSortedTagsText(tiddler); return "* {{{"+(context.lastGroup?context.lastGroup:"no tags")+"}}}\sn";} else return "";} '\n write\n 'getGroupTitle(tiddler, context)+"** [[" + tiddler.title+"]]\sn"'\n>>\n//(Tiddlers without tags are not included)//
{{{\n<<forEachTiddler \n where\n 'tiddler.tags.length == 0'\n>>\n}}}\n//''Result:''//\n<<forEachTiddler \n where\n 'tiddler.tags.length == 0'\n>>\nSee also [[ForEachTiddlerExamples]].
{{{\n<<forEachTiddler\n sortBy \n '(tiddler.title.toLowerCase())'\n>>\n}}}\n//''Result:''//\n<<forEachTiddler\n sortBy \n '(tiddler.title.toLowerCase())'\n>>\nSee also [[ForEachTiddlerExamples]].
For this "List" task we don't use the default action "addToList" (that simply adds all selected items to the list) but create the list using the "write" action and refer to the build-in variable "index" that is incremented for every tiddler being processed.\n{{{\n<<forEachTiddler\n where\n 'tiddler.tags.contains("basic")'\n write\n '(index < 10) ? "* [["+tiddler.title+"]]\sn" : ""'\n>>\n}}}\nIn the write parameter there is a conditional output: when we are processing the tiddlers 0 to 9 it will write a line with:\n\n {{{* [[theTiddlerName]]}}}\n\nTiddler 10 and the following ones will generate no output (as the empty string is specified).\n\n''//Result://''\n<<forEachTiddler\n where\n 'tiddler.tags.contains("basic")'\n write\n '(index < 10) ? "* [["+tiddler.title+"]]\sn" : ""'\n>>\n
{{{\n<<forEachTiddler\n where\n 'tiddler.tags.contains("basic")'\n script\n '\n function getFirstLine(s) {\n var m = s.match(/\ss*(.*)/);\n return m != null && m.length >= 1 ? m[1] : "";\n }\n '\n write\n '"*[["+tiddler.title+"]] → "+getFirstLine(tiddler.text)+"\sn"' \n>>\n}}}\n<<forEachTiddler\n where\n 'tiddler.tags.contains("basic")'\n script\n '\n function getFirstLine(s) {\n var m = s.match(/\ss*(.*)/);\n return m != null && m.length >= 1 ? m[1] : "";\n }\n '\n write\n '"*[["+tiddler.title+"]] → "+getFirstLine(tiddler.text)+"\sn"' \n>>\n
{{{\n<<forEachTiddler\n in \n 'file:///c:/SampleTiddlyWiki.html'\n write\n 'tiddler.title+"\sn"'\n>>\n}}}\n<<forEachTiddler\n in \n 'file:///c:/SampleTiddlyWiki.html'\n write\n 'tiddler.title+"\sn"'\n>>\n\n
<<forEachTiddler\n where\n 'tiddler.text.contains("title")'\n>>\nSee also ForEachTiddlerExamples.
[[Compiling MPlayer on Mac OS X Tiger|http://www.jonsimpson.co.uk/weblog/2005-11-14/compiling-mplayer-on-mac-os-x-tiger.html]]\n[[Compiling mplayer-cvs on Mac OS X 10.4 Tiger|http://www.jonsimpson.co.uk/weblog/2005-12-05/compiling-mplayer-cvs-on-mac-os-x-104-tiger.html]]
Taken liberally from http://code.google.com/p/macfuse/wiki/HOWTO\n!Installing MacFUSE from Source\nThe MacFUSE subversion repository is located at:\n\nhttp://code.google.com/p/macfuse/\n\nYou can anonymously check out the latest project source code as follows:\n{{{\nsvn checkout http://macfuse.googlecode.com/svn/trunk/ macfuse\n}}}\nIf you have developer access to the repository, you can do the following:\n{{{\nsvn checkout https://macfuse.googlecode.com/svn/trunk macfuse --username <user>\n}}}\nThe following are some of the key components of the repository:\n{{{\nfilesystems/\n |_ sshfs/\n |_ sshfs-fuse-<version>-macosx.patch # Mac OS X patches for sshfs\n fusefs/ # Mac OS X FUSE kernel extension\n libfuse/\n |_ fuse-<version>-macosx.patch # Mac OS X patches for libfuse\n util/ # Miscellaneous utilities and scripts\n}}}\nCompile fusefs.kext\n{{{\n$ cd fusefs # Go to the kernel extension source directory\n$ xcodebuild -target fusefs -configuration Release\n}}}\nThis will build the kext as build/Release/fusefs.kext. The kext should go in /Library/Extensions/ and must have the appropriate permissions.\n{{{\n$ sudo mkdir -p /Library/Extensions/\n$ sudo chown root:admin /Library\n$ sudo chown root:wheel /Library/Extensions\n$ sudo chmod +t /Library\n$ sudo cp -pR build/Release/fusefs.kext /Library/Extensions/\n$ sudo chown -R root:wheel /Library/Extensions/fusefs.kext\n}}}\nCompile load_fusefs\n{{{\n$ xcodebuild -target load_fusefs -configuration Release\n}}}\nload_fusefs is a small helper program that the MacFUSE user library calls to load fusefs.kext if the latter isn't already loaded. Note that load_fusefs needs to be installed setuid root. It is installed as a resource within the fusefs.kext bundle.\n{{{\n$ sudo cp build/Release/load_fusefs /Library/Extensions/fusefs.kext/Contents/Resources/\n$ sudo chown root:wheel /Library/Extensions/fusefs.kext/Contents/Resources/load_fusefs\n$ sudo chmod u+s /Library/Extensions/fusefs.kext/Contents/Resources/load_fusefs\n}}}\nCopy the fusefs.fs bundle to its destination\n{{{\n$ sudo cp -pR fusefs.fs /System/Library/Filesystems/\n$ sudo chown -R root:wheel /System/Library/Filesystems/fusefs.fs\n}}}\nCompile mount_fusefs\n{{{\n$ xcodebuild -target mount_fusefs -configuration Release\n}}}\nmount_fusefs is called by the MacFUSE user library to perform the mount() system call. It is installed within the fusefs.fs bundle (setuid root is not required).\n{{{\n$ sudo cp build/Release/mount_fusefs /System/Library/Filesystems/fusefs.fs/\n$ sudo chown root:wheel /System/Library/Filesystems/fusefs.fs/mount_fusefs\n}}}\nNB: The sshfs binary package available from this project's website contains an sshfs-static binary that is statically linked against glib (but dynamically linked against libfuse). If you wish to quickly try out sshfs, you can just install the MacFUSE Core package and use sshfs-static without having to compile anything.\n\n!Compiling FUSE filesystems from source\nCompiling pkg-config\n{{{\n$ tar -xzvf pkg-config-<version>.gz\n$ cd pkg-config-<version>/\n$ CFLAGS="-O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" LDFLAGS="-arch i386 -arch ppc" ./configure --prefix=/usr/local --disable-dependency-tracking\n$ make\n$ sudo make install\n}}}\nCompiling fuse\n{{{\n$ tar -xzvf fuse-2.6.1.tar.gz\n$ cd fuse-2.6.1\n$ patch -p1 < /path/to/fuse-2.6.1-macosx.patch\n...\n$ CFLAGS="-D__FreeBSD__=10 -D_POSIX_C_SOURCE=200112L -O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" LDFLAGS="-arch i386 -arch ppc" ./configure --prefix=/usr/local --disable-dependency-tracking\n$ make\n$ sudo make install\n}}}\nCompiling getext\n{{{\n$ tar -xzvf gettext-0.16.1.tar.gz\n$ cd gettext-0.16.1\n$ CFLAGS="-O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" LDFLAGS="-arch i386 -arch ppc -fno-common" ./configure --prefix=/usr/local --disable-dependency-tracking --with-libiconv-prefix=/Developer/SDKs/MacOSX10.4u.sdk/usr\n$ make\n$ sudo make install\n}}}\nCompiling glib\n{{{\n$ tar -xzvf glib-2.12.7.tar.gz\n$ cd glib-2.12.7\n$ CFLAGS="-O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -I/usr/local/include" LDFLAGS="-arch i386 -arch ppc -L/usr/local/lib" ./configure --prefix=/usr/local --disable-dependency-tracking\n$ make\n$ sudo make install\n}}}\nVerify Installation\n{{{\n$ pkg-config --list-all\n...\ngmodule-export-2.0 GModule - Dynamic module loader for GLib\ngmodule-2.0 GModule - Dynamic module loader for GLib\nglib-2.0 GLib - C Utility Library\ngobject-2.0 GObject - GLib Type, Object, Parameter and Signal Library\ngthread-2.0 GThread - Thread support for GLib\ngmodule-no-export-2.0 GModule - Dynamic module loader for GLib\nfuse fuse - Filesystem in Userspace\n}}}\nCompiling sshfs\n{{{\n$ tar -xzvf sshfs-fuse-1.7.tar.gz\n$ cd sshfs-fuse-1.7\n$ patch -p1 < /path/to/sshfs-fuse-1.7-macosx.patch\n...\n$ CFLAGS="-D__FreeBSD__=10 -O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" LDFLAGS="-arch i386 -arch ppc" ./configure --prefix=/usr/local --disable-dependency-tracking\n$ sudo make install\n}}}\nWhen running the configure script for a file system, you need to have -D__FreeBSD__=10 in CFLAGS. This is critical!
[[MacForge|http://www.macforge.net/]]\n[[Mac Libre|http://www.maclibre.org]]
Macros are one of the most powerful features Jeremy Ruston has added to TiddlyWiki. With it, you can add new features to TiddlyWiki without hacking into the source code. Several macros are preinstalled with TiddlyWiki by default, and many others are available on del.icio.us, tagged as [[TiddlyWikiPlugin|http://del.icio.us/tag/tiddlywikiplugin]]. Several TiddlyWiki macro repositories can be found [[here|http://del.icio.us/tag/tiddlywikiplugin]].\n\nThe following is a list of the macros that come preinstalled with TiddlyWiki.\n{{moveover{\n*[[today]]\n*[[tag]]\n*[[newJournal]]\n*[[newTiddler]]\n*[[tiddler]]\n*[[slider]]\n*[[version]]\n*[[list]]\n*[[tabs]]\n*[[Sparklines]]\n*[[GradientMacro]]\n*[[TaggingMacro]]\n*[[ToolbarMacro]]\n}}}\nIt's also easy to add [[CustomMacros]].
[[Journal]] [[Interesting]] [[ReferenceGuide]]\n
<!--{{{-->\n<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>\n<!--}}}-->\n\n<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>Guru Notebook</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>
/***\n|''Name:''|Minesweeper|\n|''Version:''|0.72 (12 Oct 2005)|\n|''Source:''|Tiddly W;nks (http://www.bur.st/~blazeoz/tiddlywinks/)|\n|''Author:''|[[Daniel Baird]]|\n|''Type:''|Macro|\n!Description\nIt's minesweeper!\n\n!Syntax/Example usage\n{{{<<minesweeper>>}}} or {{{<<minesweeper [width] [height] [bombs]>>}}}\n<<minesweeper>>\n\n!Notes\n* Let me know if you want graphics, or that MSWindows Minesweeper thing where you can click with both buttons on a numbered square, and it does the thinking for you..\n\n!Revision History\n* 0.5.0 (2-Oct-05)\n** original version (Daniel)\n* 0.5.1 (3-Oct-05)\n** added the css styles via set~StyleSheet (Simon)\n* 0.5.2 (3-Oct-05)\n** added parameters to macro and fixed bug preventing detection of win (Simon)\n* 0.6 (5-Oct-05)\n** Fixed the problem with multiple games on screen at once.\n** Cleaned up the JavaScript warning generated when you clicked anywhere but on a square.\n* 0.7 (6-Oct-05)\n** Integrated sweet additions from Genesis_mage (genisis329 at gmail dot com) that:\n*** allows winning by having all non-mines clicked (without having to mark every mine)\n*** added a mark button to mark and unmark mines without the keyboard\n** Win time now shows tenths of a second.\n* 0.71 (10-Oct-05)\n** tweaked a style to make the mark button work better in IE\n* 0.72 (12-Oct-05)\n** worked out how to use a closure as a event handler, which means that the code added in 0.6 could be made a lot simpler.\n\n***/\n/*{{{*/\n\nversion.extensions.minesweeper = {major: 0, minor: 7, revision: 2};\n\nconfig.macros.minesweeper = {};\n\nconfig.macros.minesweeper.handler = function(place,macroName,params) {\n var width = params[0];\n var height = params[1];\n var bombs = params[2];\n\n if (width == undefined) width = 9;\n if (height == undefined) height = width;\n if (bombs == undefined) bombs = Math.round(width * height / 8)\n if (bombs > width * height) bombs = width * height;\n\n var aGame = new MinesweeperGame();\n\n createTiddlyElement(place,'div',aGame.id,null,'If you see this, Minesweeper is broken. Let Daniel know (DanielBaird at gmail dot com).');\n aGame.newGame(width, height, bombs);\n}\n// =======================================================================\nfunction MinesweeperGame() {\n this.idprefix = 'mines';\n this.version = '0.72 beta';\n this.id = this.idprefix + MinesweeperGame.prototype.nextid;\n MinesweeperGame.prototype.nextid++;\n return this;\n}\n// -----------------------------------------------------------------------\nMinesweeperGame.prototype.nextid = 0;\n// -----------------------------------------------------------------------\nMinesweeperGame.prototype.newGame = function(height, width, mines) {\n this.height = height;\n this.width = width;\n this.mines = mines;\n this.total = height * width;\n this.markMode = false;\n\n this.startGame();\n}\n// -----------------------------------------------------------------------\nMinesweeperGame.prototype.startGame = function() {\n\n this.gamestate = 'ready';\n this.clicks = 0;\n this.marks = 0;\n this.message = 'click on the board to begin';\n\n this.starttime = null;\n this.wintime = null;\n this.board = new Array();\n\n // create the squares\n for (var x = 0; x < this.height; x++) {\n var row = new Array();\n for (var y = 0; y < this.width; y++) {\n row.push( {count: 0, mine: false, clicked: false, marked: false} );\n }\n this.board.push(row);\n }\n\n // add mines\n for (var m = 0; m < this.mines; m++) {\n var mx = Math.round((this.height-1)*Math.random());\n var my = Math.round((this.width-1)*Math.random());\n if (this.board[mx][my].mine) {\n m--;\n } else {\n this.board[mx][my].mine = true;\n }\n }\n\n // work out counts\n for (var cx = 0; cx < this.height; cx++) {\n for (var cy = 0; cy < this.width; cy++) {\n var count = 0;\n for (var dx = -1; dx < 2; dx++) {\n for (var dy = -1; dy < 2; dy++) {\n var nx = cx + dx;\n var ny = cy + dy;\n if ( (!(dx==0 && dy==0))\n && (nx >= 0) && (nx < this.height)\n && (ny >= 0) && (ny < this.width)\n && this.board[nx][ny].mine) {\n count++;\n }\n }\n }\n this.board[cx][cy].count = count;\n }\n }\n this.showBoard();\n}\n// -----------------------------------------------------------------------\nMinesweeperGame.prototype.showBoard = function() {\n var node = document.getElementById(this.id);\n var html = new Array();\n html.push('<table class="minefield" cellspacing="2">');\n html.push('<tr><td class="info" colspan="'+this.width+'">');\n html.push('Minesweeper '+this.version+'<br /><b>'+this.gamestate+'</b>');\n if (this.gamestate == 'playing') {\n this.message = (this.mines - this.marks)+' mines unmarked';\n }\n html.push('</td></tr>');\n for (var x = 0; x < this.height; x++) {\n html.push('<tr>');\n for (var y = 0; y < this.width; y++) {\n html.push( this.makeSquare(x,y) );\n }\n html.push('</tr>');\n }\n var cls = 'un';\n if (this.markMode) cls = '';\n html.push('<tr><td id="'+this.id+'_markbtn" class="'+cls+'clicked widebtn" colspan="'+this.width+'">mark / unmark mines</td></tr>');\n html.push('<tr><td class="info" colspan="'+this.width+'">'+this.message);\n html.push('<small>');\n html.push('<br /><span class="minesweeper' + cls + 'show">ctrl- shift- or alt-</span>click to reveal a square');\n html.push('<br /><span class="minesweeper' + cls + 'hide">ctrl- shift- or alt-</span>click to mark a mine');\n html.push('</small>');\n html.push('</td></tr>');\n html.push('</table>');\n node.innerHTML = html.join('');\n node.onclick = this.getClickHandler();\n}\n// -----------------------------------------------------------------------\nMinesweeperGame.prototype.makeSquare = function(x,y) {\n var sq = this.board[x][y];\n var reveal = (this.gamestate != 'playing' && this.gamestate != 'ready');\n var html = new Array();\n if (sq.clicked) {\n html.push('<td class="clicked" id="'+this.id+'_x-'+x+'_y-'+y+'">');\n if (!sq.marked && reveal && sq.mine) {\n html.push('B!');\n } else if (!sq.marked && reveal && sq.mine) {\n html.push('B!');\n } else if (sq.count > 0){\n html.push(sq.count);\n } else {\n html.push(' ');\n }\n } else {\n html.push('<td class="unclicked" id="'+this.id+'_x-'+x+'_y-'+y+'">');\n if (sq.marked && !reveal) {\n html.push('B?');\n } else if (sq.marked && sq.mine && reveal) {\n html.push('B');\n } else if (sq.marked && !sq.mine && reveal) {\n html.push('X');\n } else if (sq.mine && reveal) {\n html.push('B!');\n } else {\n html.push(' ');\n }\n }\n html.push('</td>');\n return html.join('');\n}\n// -------------------------------------------------------------------\nMinesweeperGame.prototype.clickSquare = function(cx,cy,modifier) {\n if (this.gamestate == 'ready') {\n this.starttime = new Date();\n this.gamestate = 'playing';\n }\n if (this.gamestate == 'playing') {\n if (!this.board[cx][cy].clicked) {\n if ( (modifier && !this.markMode) || (!modifier && this.markMode) ) {\n if (this.board[cx][cy].marked) {\n this.marks--;\n this.board[cx][cy].marked = false;\n } else {\n this.marks++;\n this.board[cx][cy].marked = true;\n }\n } else if (!this.board[cx][cy].clicked && !this.board[cx][cy].marked) {\n this.revealSquare(cx,cy);\n }\n this.markMode = false;\n }\n this.checkWin();\n this.showBoard();\n } else {\n // clicked when we're not playing..\n this.startGame();\n }\n}\n// -------------------------------------------------------------------\nMinesweeperGame.prototype.revealSquare = function(x,y) {\n if (this.board[x][y].clicked == false && this.board[x][y].marked == false) {\n this.board[x][y].clicked = true;\n this.clicks++;\n if (this.board[x][y].mine) {\n this.gamestate = 'boom!';\n this.message = 'click board to play again';\n } else if (this.board[x][y].count == 0) {\n // if it's a zero, we might have to reveal some other squares..\n for (var dx = -1; dx < 2; dx++) {\n for (var dy = -1; dy < 2; dy++) {\n var nx = x + dx;\n var ny = y + dy;\n if ( (!(dx==0 && dy==0)) && (nx >= 0) && (nx < this.height) && (ny >= 0) && (ny < this.width) ) {\n this.revealSquare(nx,ny);\n }\n }\n }\n }\n }\n}\n// -------------------------------------------------------------------\nMinesweeperGame.prototype.handleClick = function(e) {\n // work out which cell was clicked\n if (!e) var e = window.event;\n var str = resolveTarget(e).id;\n if (str && str != undefined) {\n if (str == this.id + '_markbtn') {\n this.markMode = !this.markMode;\n this.showBoard();\n } else {\n var cx = parseInt(str.substr( str.indexOf('x-')+2 ));\n var cy = parseInt(str.substr( str.indexOf('y-')+2 ));\n if ( !isNaN(cx) && !isNaN(cy) ) {\n this.clickSquare(cx,cy,(e.altKey || e.shiftKey || e.ctrlKey));\n }\n }\n }\n}\n// -------------------------------------------------------------------\nMinesweeperGame.prototype.getClickHandler = function() {\n var thisGame = this;\n return function(e) {\n thisGame.handleClick(e);\n }\n}\n// -------------------------------------------------------------------\nMinesweeperGame.prototype.checkWin = function() {\n if (this.clicks == this.total - this.mines && this.gamestate !='boom!') {\n this.gamestate = 'win';\n this.wintime = new Date();\n this.message = 'You won in '+Math.round(((this.wintime - this.starttime)/100))/10+' seconds';\n this.message = this.message + '<br />click board to play again';\n }\n}\n// -----------------------------------------------------------------------\n\nsetStylesheet(\n ".viewer .minefield { "+\n "background: #ddd; "+\n "border: double 3px black; "+\n "border-collapse: separate; "+\n "border-spacing: 2px; "+\n "} \sn"+\n\n ".viewer .minefield td { "+\n "cursor: default; "+\n "width: 1.3em; "+\n "height: 1.1em; "+\n "text-align: center; "+\n "vertical-align: center; "+\n "background: #ddd; "+\n "border: 1px solid #ccc; "+\n "} \sn"+\n\n ".viewer .minefield td.info, .viewer .minefield td.widebtn { "+\n "width: auto; "+\n "} \sn"+\n\n ".minesweeperhide, .minesweeperunshow { "+\n "display: none; "+\n "} \sn"+\n\n ".viewer .minefield td.unclicked { "+\n "cursor: pointer; "+\n "border-color: #fff; "+\n "border-right-color: #999; "+\n "border-bottom-color: #999; "+\n "} \sn"+\n "",\n "MinesweeperGame");\n\n/*}}}*/\n
In monospaced text, also known as non-proportional text, all the characters are of an equal width. So while in a normal font, i is thinner than W is, in {{{monospaced text, i and W are the same width}}}. It is primarily used in programming manuals and sites to identify blocks of code. \n\nAlso, <<tag Formatting>> and [[macros|Macros]] that are in a monospaced block are not executed. For example:\n\n{{{\n<<today>>\n}}}\n\nTo add a monotype text block, enclose the text in triple squiggly-brackets: \n{{{\n{{{This is monotype}}}\n}}}
/***\n| Name:|MptwLayoutPlugin|\n| Description:|A package containing templates and css for the MonkeyPirateTiddlyWiki layout|\n| Version:|6.1.2|\n| Date:|02-Oct-2006|\n| Source:|http://mptw.tiddlyspot.com/#MptwLayoutPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\n!Notes\nPresumes you have TagglyTaggingPlugin installed.\n***/\n//{{{\nconfig.shadowTiddlers.GettingStarted += "\sn\snSee also MonkeyPirateTiddlyWiki.";\n\n//}}}\n\n//{{{\nmerge(config.shadowTiddlers,{\n\nMonkeyPirateTiddlyWiki:[\n "[[MonkeyPirateTiddlyWiki|http://mptw.tiddlyspot.com]] is a distribution of [[TiddlyWiki|http://www.tiddlywiki.com/]] created by Simon Baird. See [[the web site|http://mptw.tiddlyspot.com/]] for more information.",\n "!!Upgrading ~MonkeyPirateTiddlyWiki",\n "This \s"empty\s" ~MonkeyPirateTiddlyWiki file comes pre-installed with the core ~MonkeyPirateTiddlyWiki plugins. You can upgrade these core plugins to the latest version by doing the following:",\n "# Click ImportTiddlers",\n "# Click \s"Choose...\s" and select \s"~MptwUpgradeURL\s"",\n "# Click \s"fetch\s"",\n "# Click the checkbox in the first column heading to select all tiddlers",\n "# Click \s"More actions...\s" and select \s"Import these tiddlers\s"",\n "# Click \s"OK\s" to confirm you want to overwrite the tiddlers",\n ""\n].join("\sn"),\n\nMptwStyleSheet:[\n "/*{{{*/",\n "/* a contrasting background so I can see where one tiddler ends and the other begins */",\n "body {",\n " background: [[ColorPalette::TertiaryLight]];",\n "}",\n "",\n "/* sexy colours and font for the header */",\n ".headerForeground {",\n " color: [[ColorPalette::PrimaryPale]];",\n "}",\n ".headerShadow, .headerShadow a {",\n " color: [[ColorPalette::PrimaryMid]];",\n "}",\n ".headerForeground, .headerShadow {",\n " padding: 1em 1em 0;",\n " font-family: 'Trebuchet MS' sans-serif;",\n " font-weight:bold;",\n "}",\n ".headerForeground .siteSubtitle {",\n " color: [[ColorPalette::PrimaryLight]];",\n "}",\n ".headerShadow .siteSubtitle {",\n " color: [[ColorPalette::PrimaryMed]];",\n "}",\n "",\n "/* make shadow go and down right instead of up and left */",\n ".headerShadow {",\n " left: 1px;",\n " top: 1px;",\n "}",\n "",\n "/* prefer monospace for editing */",\n ".editor textarea {",\n " font-family: 'Consolas' monospace;",\n "}",\n "",\n "/* sexy tiddler titles */",\n ".title {",\n " font-size: 250%;",\n " color: [[ColorPalette::PrimaryLight]];",\n " font-family: 'Trebuchet MS' sans-serif;",\n "}",\n "",\n "/* more subtle tiddler subtitle */",\n ".subtitle {",\n " padding:0px;",\n " margin:0px;",\n " padding-left:0.5em;",\n " font-size: 90%;",\n " color: [[ColorPalette::TertiaryMid]];",\n "}",\n ".subtitle .tiddlyLink {",\n " color: [[ColorPalette::TertiaryMid]];",\n "}",\n "",\n "/* a little bit of extra whitespace */",\n ".viewer {",\n " padding-bottom:3px;",\n "}",\n "",\n "/* don't want any background color for headings */",\n "h1,h2,h3,h4,h5,h6 {",\n " background: [[ColorPalette::Background]];",\n " color: [[ColorPalette::Foreground]];",\n "}",\n "",\n "/* give tiddlers 3d style border and explicit background */",\n ".tiddler {",\n " background: [[ColorPalette::Background]];",\n " border-right: 2px [[ColorPalette::TertiaryMid]] solid;",\n " border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;",\n " margin-bottom: 1em;",\n " padding-bottom: 2em;",\n "}",\n "",\n "/* make options slider look nicer */",\n "#sidebarOptions .sliderPanel {",\n " border:solid 1px [[ColorPalette::PrimaryLight]];",\n "}",\n "",\n "",\n "/* the borders look wrong with the body background */",\n "#sidebar .button {",\n " border-style: none;",\n "}",\n "",\n "/* displays the list of a tiddler's tags horizontally. used in ViewTemplate */",\n ".tagglyTagged li.listTitle {",\n " display:none",\n "}",\n ".tagglyTagged li {",\n " display: inline; font-size:90%;",\n "}",\n ".tagglyTagged ul {",\n " margin:0px; padding:0px;",\n "}",\n "",\n "/* this means you can put line breaks in SidebarOptions for readability */",\n "#sidebarOptions br {",\n " display:none;",\n "}",\n "/* undo the above in OptionsPanel */",\n "#sidebarOptions .sliderPanel br {",\n " display:inline;",\n "}",\n "",\n "/* horizontal main menu stuff */",\n "#displayArea {",\n " margin: 1em 15.7em 0em 1em; /* use the freed up space */",\n "}",\n "#topMenu br {",\n " display: none;",\n "}",\n "#topMenu {",\n " background: [[ColorPalette::PrimaryMid]];",\n " color:[[ColorPalette::PrimaryPale]];",\n "}",\n "#topMenu {",\n " padding:2px;",\n "}",\n "#topMenu .button, #topMenu .tiddlyLink, #topMenu a {",\n " margin-left: 0.5em;",\n " margin-right: 0.5em;",\n " padding-left: 3px;",\n " padding-right: 3px;",\n " color: [[ColorPalette::PrimaryPale]];",\n " font-size: 115%;",\n "}",\n "#topMenu .button:hover, #topMenu .tiddlyLink:hover {",\n " background: [[ColorPalette::PrimaryDark]];",\n "}",\n "@media print {",\n " #topMenu {",\n " display: none ! important;",\n " }",\n "}",\n "/*}}}*/",\n ""\n].join("\sn"),\n\nMptwViewTemplate:[\n "<!--{{{-->",\n "<div class='toolbar'>",\n " <!-- some custom contextual checkboxes -->",\n " <span style=\s"padding-right:2em;\s">",\n " <span macro=\s"showWhen tiddler.tags.contains('systemConfig')\s">",\n " <span macro=\s"toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'\s"></span>",\n " <!-- <span macro=\s"toggleTag systemConfigForce . '[[force|systemConfigForce]]'\s"></span> -->",\n " </span>",\n " <span macro=\s"showWhen config.macros.applyLayout && tiddler.tags.contains('layout')\s">",\n " <span macro=\s"applyLayout\s"></span>",\n " </span>",\n " </span>",\n " <!-- regular toolbar -->",\n " <span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler undoChanges permalink references jump newHere newJournalHere'></span>",\n "</div>",\n "<!-- regular tags macro but uses taggly css -->",\n "<div class=\s"tagglyTagged\s" macro=\s"tags\s"></div>",\n "<div>",\n " <span class='title' macro='view title'></span>",\n " <span macro=\s"miniTag\s"></span>",\n "</div>",\n "<div class='subtitle'>",\n " <span macro='view modifier link'></span>,",\n " <span macro='view modified date [[DD-mmm-YY]]'></span>",\n " (<span macro='message views.wikified.createdPrompt'></span>",\n " <span macro='view created date [[DD-mmm-YY]]'></span>)",\n "</div>",\n "<!-- using taggly versions of these two",\n "<div class='tagging' macro='tagging'></div>",\n "<div class='tagged' macro='tags'></div> -->",\n "<div macro=\s"hideWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')\s">",\n " <div class='viewer' macro='view text wikified'></div>",\n "</div>",\n "<div macro=\s"showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')\s">",\n " <div class='viewer'><pre macro='view text'></pre></div>",\n "</div>",\n "<div class=\s"tagglyTagging\s" macro=\s"tagglyTagging\s"></div>",\n "<div class='tagClear'></div>",\n "<!--}}}-->",\n ""\n].join("\sn"),\n\nMptwPageTemplate:[\n "<!--{{{-->",\n "<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>",\n " <div class='headerShadow'>",\n " <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> ",\n " <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>",\n " </div>",\n " <div class='headerForeground'>",\n " <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span> ",\n " <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>",\n " </div>",\n "</div>",\n "<!-- horizontal MainMenu -->",\n "<div id='topMenu' refresh='content' tiddler='MainMenu'></div>",\n "<!-- original MainMenu menu -->",\n "<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></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>",\n "<!--}}}-->",\n ""\n].join("\sn"),\n\nMptwEditTemplate:[\n "<!--{{{-->",\n "<div class=\s"toolbar\s" macro=\s"toolbar +saveTiddler closeOthers cancelTiddler deleteTiddler\s"></div>",\n "<div class=\s"title\s" macro=\s"view title\s"></div>",\n "<div class=\s"editLabel\s">Title</div><div class=\s"editor\s" macro=\s"edit title\s"></div>",\n "<div class=\s"editLabel\s">Tags</div><div class=\s"editor\s" macro=\s"edit tags\s"></div>",\n "<div class=\s"editorFooter\s"><span macro=\s"message views.editor.tagPrompt\s"></span><span macro=\s"tagChooser\s"></span></div>",\n "<div class=\s"editor\s" macro=\s"edit text\s"></div>",\n "<!--}}}-->",\n ""\n].join("\sn")\n\n});\n//}}}\n
URL: http://mptw.tiddlyspot.com/upgrade.html\n
!Repair a Corrupted Database\n\nWhen your database is corrupted you could see in /var/log/messages that the MySQL database is corrupted. To repair the database, launch the mysqlcheck command as root:\n\n{{{mysqlcheck -p --auto-repair --all-databases}}}\n\n
You can run NBShell with the following python script\n{{{\nimport nbshell\nbshell.start()\n}}}\nor you can run the file start.py which is in the directory where you\ndownloaded the source like this\n{{{\npython2.4 start.py\n}}}
[[Neuro-Evolving Robotic Operatives|http://www.nerogame.org/]]\n[[AI vs. AI:NERO Writeup|http://www.linux.com/article.pl?sid=06/10/03/2139203]]\n[[NERO Forum|http://z.cs.utexas.edu/users/nn/nero/forums/]]\n[[Ken Stanley|http://z.cs.utexas.edu/users/nn/nero/forums/]]\n[[NEAT (NeuroEvolution of Augmenting Topologies)|http://www.cs.utexas.edu/users/nn/project-view.php?RECORD_KEY(Projects)=ProjID&ProjID(Projects)=14]]
Lets you find services including wireless hotspots.\n\nhttp://gis.nyc.gov/doitt/mp/Portal.do
[[Suse Linux Internals - Chapter 20: NFS - Network File System|http://linuxmafia.com/pub/linux/suse-linux-internals/chapter20.html]]\n[[nisnfs|http://linuxmafia.com/faq/Network_Other/nisnfs.html]]\n[[HOWTO Encrypt Your Home Directory Using CFS|http://gentoo-wiki.com/HOWTO_Encrypt_Your_Home_Directory_Using_CFS]]\n[[NFS-HOWTO|http://tldp.org/HOWTO/NFS-HOWTO/index.html]]\n[[Diskless-root-NFS-HOWTO|http://tldp.org/HOWTO/Diskless-root-NFS-HOWTO.html]]\n[[HOWTO Access NFS via SFU|http://gentoo-wiki.com/HOWTO_Access_NFS_via_SFU]]\n[[Diskless Nodes with Gentoo|http://www.gentoo.org/doc/en/diskless-howto.xml]]
[[Suse Linux Internals - Chapter 15: NIS - Network Information Service|http://linuxmafia.com/pub/linux/suse-linux-internals/chapter15.html]] AKA Yellow Pages\n[[nisnfs|http://linuxmafia.com/faq/Network_Other/nisnfs.html]]\n[[NIS-HOWTO|http://tldp.org/HOWTO/NIS-HOWTO/index.html]]\n[[How to Setup NIS|http://gentoo-wiki.com/HOWTO_Setup_NIS]]
/***\n| Name:|NewHerePlugin|\n| Description:|Creates the new here and new journal toolbar commands|\n| Version:|6.1.6|\n| Date:|06-Oct-2006|\n| Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\nTo use edit your ViewTemplate and add newHere to the toolbar div, eg\n{{{<div class='toolbar' macro='toolbar ... newHere'></div>}}}\nNote: would be good if we could do this instead some day\n{{{<<newTiddler tag:{{tiddler.title}} label:'new here'>>}}}\n***/\n//{{{\nmerge(config.commands,{\n\n newHere: {\n text: 'new here',\n tooltip: 'Create a new tiddler tagged as this tiddler',\n hideReadOnly: true,\n handler: function(e,src,title) {\n if (!readOnly) {\n clearMessage();\n var t=document.getElementById('tiddler'+title);\n story.displayTiddler(t,config.macros.newTiddler.title,DEFAULT_EDIT_TEMPLATE);\n story.setTiddlerTag(config.macros.newTiddler.title, title, 0);\n story.focusTiddler(config.macros.newTiddler.title,"title"); // doesn't work??\n return false;\n }\n }\n },\n\n newJournalHere: {\n //text: 'new journal here', // too long\n text: 'new journal',\n hideReadOnly: true,\n dataFormat: 'DD MMM YYYY', // adjust to your preference\n //dataFormat: 'YYYY-0MM-0DD', \n tooltip: 'Create a new journal tiddler tagged as this tiddler',\n handler: function(e,src,title) {\n if (!readOnly) {\n clearMessage();\n var now = new Date();\n var t=document.getElementById('tiddler'+title);\n var newtitle = now.formatString(this.dataFormat)\n story.displayTiddler(t,newtitle,DEFAULT_EDIT_TEMPLATE);\n story.setTiddlerTag(newtitle, title, 0);\n story.focusTiddler(newtitle,"title");\n return false;\n }\n }\n }\n\n});\n//}}}\n
[[Replace NIS with Kerberos and LDAP|http://aput.net/~jheiss/krbldap/]]
!Self-signed certificates\n\nYou can create a self-signed certificate using the req command provided with OpenSSL, like this:\n{{{\n openssl req -x509 -newkey rsa:1024 -keyout file1 -out file2 \s\n -days 9999 -nodes\n}}}\nfile1 and file2 can be the same file; the key and the certificate are delimited and so can be identified independently. The -days option specifies a period for which the certificate is valid. The -nodes option is important: if you do not set it, the key is encrypted with a passphrase that you are prompted for, and any use that is made of the key causes more prompting for the passphrase. This is not helpful if you are going to use this certificate and key in an MTA, where prompting is not possible.\n\nA self-signed certificate made in this way is sufficient for testing, and may be adequate for all your requirements if you are mainly interested in encrypting transfers, and not in secure identification.\n\nHowever, many clients require that the certificate presented by the server be a user (also called ``leaf'' or ``site'') certificate, and not a self-signed certificate. In this situation, the self-signed certificate described above must be installed on the client host as a trusted root certification authority (CA), and the certificate used by Exim must be a user certificate signed with that self-signed certificate.\n\nFor information on creating self-signed CA certificates and using them to sign user certificates, see the General implementation overview chapter of the Open-source PKI book, available online at http://ospkibook.sourceforge.net/.\n\n!Certificate Installation with OpenSSL - Other People's Certificates\nGuides In This Section\n\n * Installing CA Certificates into the OpenSSL framework\n * Installing Remote Server Certificates into the OpenSSL framework\n * Installing Self Signed Certificates into the OpenSSL framework\n * Installing and using CRLs (Certificate Revocation Lists) within the OpenSSL or Apache framework\n * Installing CA Certificates on Mac OSX for use by it, Safari etc\n * Installing CA Certificates for use with OpenLDAP \n\nInstalling Remote Server Certificates into the OpenSSL framework\n\nNote: In the case of self signed remote server certificates, you need this guide\n\nThis is where you want to install the certificate for just one server, when you don't want to install the certificate for the CA that signed the server certificate. Normally you wouldn't want to do this, as by installing the CA certificate you will be able to connect to other servers with certificates signed by the same CA without further effort.\n\nProbably the only time you would want to install only the certificate for one server but not for the CA is where you only trust the server opperator, but not their CA. However, in this case I'd suggest you start prodding the server opperator to get their certificates from a more trust-worthy supplier...\n\nIf you do only want to add the server certificate and not the CA, it is supprisingly simple. As far as OpenSSL is concerned, there is very little difference between a self signed certificate and a server certificate for a non trusted CA - they both require a highest level trusted entity of themselves.\nThus, you just just treat the server certificate as if it were a self signed server certificate, and install that as per the guide below.\nInstalling Self Signed Certificates into the OpenSSL framework\n\nThis bit of the document isn't quite finished. As a quick hack, follow the CA Certificate Install Guide, but with both the server certificate and the CA certificate being the same thing, which is the self signed certificate.\n\nEventually, I'll do a seperate specific guide, honest...\n\n!!Installing CA Certificates into the OpenSSL framework\n\nFirst off, you'll need to know where your version of OpenSSL thinks its certificates, keys etc are all stored. This will depend on what version of OpenSSL you're using (not much), but more importantly, where it came from (tar ball / rpm / deb / bsd ports etc). Below are a few common places.\nFrom now on, we'll reffere to this directory as <ssl-base-dir>\n\n * AIX, OpenSSL 0.9.6 (from OpenSSH support packages) /var/ssl/\n * Cygwin, OpenSSL 0.9.6 /usr/ssl/\n * Debian Woody, OpenSSL 0.9.6 /etc/ssl/\n * Debian Sarge, OpenSSL 0.9.7 /etc/ssl/\n * Debian Etch, OpenSSL 0.9.8 /etc/ssl/\n * FreeBSD, OpenSSL 0.9.x /usr/local/openssl/\n * Gentoo, OpenSSL 0.9.6 /usr/lib/ssl/\n * Gentoo, OpenSSL 0.9.7 /etc/ssl/\n * Mac OS X 10.1.2, OpenSSL 0.9.6b /System/Library/OpenSSL/\n * Mandrake 7.1 -> 8.2, OpenSSL 0.9.6 /usr/lib/ssl/\n * NetBSD, OpenSSL 0.9.x /etc/openssl/\n * Normal OpenSSL Tarball Build, OpenSSL 0.9.6 /usr/local/ssl/\n * OpenBSD, OpenSSL 0.9.x /etc/ssl/\n * Redhat 6.2 / 7.x / 8.0 / 9, OpenSSL 0.9.6 /usr/share/ssl/\n * Redhat Enterprise 3 / 4, OpenSSL 0.9.7 /usr/share/ssl/\n * Redhat Fedora Core 2 / 3, OpenSSL 0.9.7 /usr/share/ssl/\n * Redhat Fedora Core 4, OpenSSL 0.9.7 /etc/pki/tls/\n * Redhat Fedora Core 5 / 6, OpenSSL 0.9.8 /etc/pki/tls/\n * Slackware, OpenSSL 0.9.6 /etc/ssl/\n * SuSE 7.3 / 8.0, OpenSSL 0.9.6 /usr/share/ssl/\n * SuSE 8.1 / 8.2, OpenSSL 0.9.6 /etc/ssl/ \n\nGeneral built from source, OpenSSL 0.9.x <prefix>/ssl/ (either the system default, or overriden at configure time with "--prefix foo")\n\nNote - if you run an alternate system to the above, let me know where it hides so I can add it to the list\n\nIn <ssl-base-dir>, you should find subdirectories of certs and private at a very minimum, probably a few more too (eg csr, lib, misc etc). If you don't find these two in what you think is <ssl-base-dir>, either you've got the wrong place place, or you've got a faulty open-ssl install. You can try to find it by searching for the directory "certs".\nFistly, a quick word about the files used below:\n\n * ca-certificate-file means the PEM formatted certificate of your CA.\n * server-certificate-file means the PEM formatted certificate of a server which has been signed by the CA (normally the server you were trying to connect to when you ended up here). \n\nIn the case of a self signed certificate, these two will be one and the same.\n\nBefore you can begin, you need to get the certificate from your CA. Ideally, get it in PEM format, otherwise you'll need to convert it.\n\nSlight Aside: You need to ensure there's only one CA certificate in the file from your CA. Normally there is, but ocassionally several are stored in the same file. To list the number of certificates in a file, use the command below. If you get an answer of more than one, then see the section on multiple certificates in one file. The command to check the number of certificates in a file is:\n{{{\ncat ca-certificate-file | grep 'BEGIN.* CERTIFICATE' | wc -l\n}}}\nOnce the certificate is in PEM format and you know there's only one certificate in the file, you need to verify it. First up, find the fingerprint for the CA from a trusted source (and I can't stress this one enough). Now, calculate the fingerprint for the certificate you've downloaded, and ensure they're the same. To find the fingerprint, use:\n{{{\nopenssl x509 -noout -fingerprint -in ca-certificate-file\n}}}\nAssuming they match (if they don't, you've either done something wrong, or its time to start panicing), we can install the certificate. As root (and now would be an ideal time to check you need to be root - only root should have write access, but the certs directory needs to be world readable). Copy your CA certificate to <ssl-base-dir>certs/ and finds out its Hash. OpenSSL looks for certificates using an 8 byte hash value. Calculate it with:\n{{{\nopenssl x509 -noout -hash -in ca-certificate-file\n}}}\nIn order for OpenSSL to find the certificate, it needs to be looked up as its hash. Normally, you would create a symbolic link for a meaningful name of the CA to the hash value, rather than renaming the CA certificate. Ideally, create a symbolic link (or hard link if you must, but symbolic ones usually make spotting which hash is which certificate name that bit easier). The symbolic link must be for the hashed value above plus ".0" - if you forget the .0 then OpenSSL won't detect it, and you'll get lots of errors.\nThus, I have for the current Oxford University CA:\n{{{\ndbed1725.0 pointing to oxford-ca.pem\n}}}\n(dbed1725 is the hash of the CA certificate)\n\nFor the lazy amoungst you, you might opt for the following:\n{{{\nln -s my_ca.crt `openssl x509 -hash -noout -in my_ca.crt`.0\n}}}\nWe're now to test this installation. To do so, we really want a certificate that's been signed by the newly installed CA. Failing this, you can use the CA certificate, but this won't always cause all the possible errors to show up. Run:\n{{{\nopenssl verify -CApath <ssl-base-dir>certs server-certificate-file\n}}}\nIf you've got it correct, you should see something like:\n{{{\noxford-herald2-server.pem: OK\n}}}\nWhich tells you that your CA certificate is correctly installed.\n\nHowever, if you see something like:\n{{{\noxford-ca.pem: /C=GB/ST=Oxfordshire/L=Oxford/O=Oxford University/OU=Computing Services/CN=Oxford University Computing Services CA/Email=ca@computing-services.oxford.ac.uk\nerror 18 at 0 depth lookup:self signed certificate\n}}}\nYou've got something wrong. Go see the errors page for more information, and probable causes.\nUsing a CRL\n\nIn order to check that the certificate you've just been presented (for whatever reason) is still valid (and hasn't been revoked), you'll need to check a CRL (certificate revocation list). These are published by CAs.\n\nIn most cases, you'll need some sort of automated script to pull (and verify!) the latest CRL of all CAs you trust, at some periodic interval. Once a week is usually good enough, unless it really matters to you that a revoked certificate can't be used, in which case you'll want a time closer to the CRL update frequency. YMMV, you'll need to decide for yourself.\n\nIn some cases, you can use an OCSP (Online Certificate Status Protocol) client (such as the one with OpenSSL) to query the CA each time. Much bigger overheads than keeping a static list, requires the CA to support it, but will allow you to start rejecting revoked certificates ASAP. It's up to you to decide if you need that or not...\nApache & CRLs:\n\nYou should already have a CRL directory, normally apache conf dir/ssl.crl/, but if not create on wherever your certificates etc live. To configure apache to check the CRL lists, add the following directive to your apache mod_ssl config block (i.e. the ssl virtual host config):\nSSLCARevocationPath crl_directory\neg SSLCARevocationPath /etc/httpd/conf/ssl.crl/\n\nYou then need, for every CRL list, to symlink it to something based on it's hash. The file will need to be called crl_hash.r0, which you can magically achieve with:\n{{{\nln -s ca.crl `openssl crl -hash -noout -in ca.crl`.r0\n}}}\n(You need to do this for every crl file in the directory).\nOpenSSL tools & CRLs:\n\nYou need to have a crl directory. Normally this will be <ssl-base-dir>/crl/, but you can change that in your openssl.cnf file (normally to be found in <ssl-base-dir>). Everyone needs to be able to read this directory (and everything in it), but no-one except the CRL fetch process should be able to write to it!\n\nYou need to symlink the CRL files to a special name based on their hash, much like you have to with the CA certificates. This time the name is hash.r0, so your friend is:\n{{{\nln -s ca.crl `openssl crl -hash -noout -in ca.crl`.r0\n}}}\n(Well, that is, unless your apache has a handy makefile to do it all for you, in which case just pop the crls in the directory and run make).\nUsing OpenSSL OCSP:\n\nMore coming soon, but for now, try the OCSP manual.\n\n!!Installing CA Certificates on Mac OSX\n\nThe tool for handling CA Certificates, server certificates etc on OSX is called "certtool".\nFirstly, make a copy of the system trusted keychain in your home directory, so you can work on it using certtool. Do that with:\n{{{\ncp /System/Library/Keychains/X509Anchors ~/Library/Keychains/\n}}}\nNow, install the PEM formatted certificate into your local trusted keychain with:\n{{{\ncerttool i mycertificate.crt k=X509Anchors\n}}}\nThis should install the certificate. If you have problems, check the certificate format (shouldn't be binary), and check the manual for certtool.\n\nOnce the certificate is in your keychain, you need to make it system wide. You do this by copying (as root / using sudo) your trusted keychain back as the system one, with something like:\n{{{\nsudo cp ~/Library/Keychains/X509Anchors /System/Library/Keychains/\n}}}\nWith that done, restart Safari, Mail etc, and they should then pick up the new CA certificate.\n\nNote that this will not affect Mac IE, Entourage etc. For those, install the certificate as normal for IE\n\n!!Installing CA Certificates for OpenLDAP\n\nOpenLDAP can be compiled against either OpenSSL, or GNUTLS. In either case, it won't use the system list of CA certificates.\n\nTo prime the server (slapd) with your CA certificate, add an entry to slapd.conf of the form:\n{{{\nTLSCACertificateFile <ssl-base-dir>/certs/ca-certificate-file\n}}}\nFor the client side (ldapsearch et al), you need to add an entry to ldap.conf (note that you may have two different copies, one in /etc/ and the other in /etc/ldap/ or /etc/openldap/) of the form:\n{{{\nTLS_CACERT <ssl-base-dir>/certs/ca-certificate-file\n}}}\n(If you use the OpenLDAP module in PHP, you'll then need to copy this ldap.conf file to .ldaprc in the home directory of the webserver.)
OperatingSystems\nPackageManagers
GentooLinux\nMacOSX
[[memcached|http://www.linuxquestions.org/linux/answers/Jeremys_Magazine_Articles/Optimizing_PHP_Part_One]]\n[[APC|http://www.linuxquestions.org/linux/answers/Jeremys_Magazine_Articles/Optimizing_PHP_Part_Two]]
[[Fink|Fink]]\nGentooPortage\nDarwinPorts
[[MptwPageTemplate]]\n
<<slideShow autostart slidePause:1000 repeat style:'MySSStyleSheet'>>\n<<photoShow photos/lisboa-*.jpg 0 3>>
/***\n|''Name:''|PhotoShowPlugin|\n|''Description:''|Photo gallery slide show|\n|''Version:''|1.0.1|\n|''Date:''|Jun 08, 2006|\n|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|\n|''Author:''|Paulo Soares (psoares (at) math (dot) ist (dot) utl (dot) pt)|\n|''License:''|[[BSD open source license]]|\n|''~CoreVersion:''|2.1.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n|''Requires:''|SlideShowPlugin|\n!Description\nThis plugin is a small companion to the SlideShowPlugin.\n\nThis plugin has been tested in Firefox, Internet Explorer, Safari, and Opera. Let us know if something seems broken.\n!Usage\nTo use this plugin you //must// be using TiddlyWiki 2.0.0. Install this tiddler and drop {{{<<photoShow directory/file-*.jpg a b>>}}} at the beginning of the tiddler. \nCheck this [[PhotoShowExample]].\n!Revision history\n1.0.1 - 08/06/2006 - made compatible with SlideShowPlugin 1.4.0\n1.0.0 - 04/01/2006 - initial release\n!Code\n***/\n//{{{\nconfig.macros.photoShow = {};\nconfig.macros.photoShow.handler= function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length<3) return;\n title = tiddler.title;\n var url = params[0];\n var first = params[1];\n var last = params[2];\n var pos = url.indexOf('*');\n\n // Grab the 'viewer' element\n var tiddlerElements = document.getElementById("tiddler"+title).childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer"){\n viewer = tiddlerElements[i];\n break;\n }\n }\n\n var pictureHolder;\n var separator;\n for(i=first; i<=last; i++){\n separator=document.createElement('HR');\n separator.className="slideSeparator";\n viewer.appendChild(separator);\n pictureHolder = document.createElement('CENTER');\n pictureHolder.appendChild(document.createElement('IMG'));\n pictureHolder.lastChild.src = url.substring(0,pos)+i+url.substring(pos+1);\n viewer.appendChild(pictureHolder);\n }\n}\n//}}}
/***\n''PhotostreamPlugin for TiddlyWiki version 2.0.x''\n^^author: Peter Bouda\nsource: http://www.peterbouda.de/PhotoStreams/#PhotostreamPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\n++++!!!!![Usage]\nThe photostream-wiki-element is another [[TiddlyBlog|http://www.peterbouda.de/downloads.html#tiddlyblog]] extension. It allows you to blog photo galleries, which you will have to create first. A typical directory structure of a photostream has to look like this:\n>photostream/ <- this name may vary\n>>title/ <- the title of your photostream; just choose one\n>>>thumbs/ <- contains thumbnails of your photos (height should not exceed 120 pixel)\n>>>medium/ <- the bigger photos\n>>nexttitle/\n... and so on. To add a photostream formatted like the above to your blog, you need a blog entry like the following:\n{{{[photostream[title|/photostream|pics1.jpg,pic2.jpg]]}}}\nThe first argument is the title, the second the base-url of your photostreams, then a comma-seperated list of your photors. Of course, the thumbnails and the photos have to have the same names. An example of this feature are my own [[photostreams|http://www.peterbouda.de/PhotoStreams/]]. If you want to automatically generate photostreams and a suitable blog entry from your photos you might find [[this script|/downloads/create_photostream.pl.txt]] usuable. You will have to an installed GD library for perl and change directory names in the script. Use it as an example.\n===\n***/\n// //+++!!!!![Code]\n//{{{\nversion.extensions.photostream = {major: 0, minor: 1, revision: 1, date: new Date(2006,2,27)};\n//}}}\n//{{{\nconfig.formatters.push( {\n name: "photostream",\n match: "\s\s[[Pp][Hh][Oo][Tt][Oo][Ss][Tt][Rr][Ee][Aa][Mm]\s\s[",\n lookahead: "\s\s[[Pp][Hh][Oo][Tt][Oo][Ss][Tt][Rr][Ee][Aa][Mm]\s\s[(?:([^\s\s|\s\s]]+)\s\s|)(?:([^\s\s|\s\s]]+)\s\s|)(?:([^\s\s|\s\s]]+))\s\s]\s\s]",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source);\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link\n {\n var e = w.output;\n var base = lookaheadMatch[2];\n var title = lookaheadMatch[1];\n var pics_string = lookaheadMatch[3];\n \n var pics = pics_string.split(',');\n \n if ( (config.browser.isIE) || (config.browser.isSafari) ) {\n var pics = pics_string.split(',');\n \n var html = '';\n for (var i=0; i<pics.length; i++) {\n pic = pics[i];\n html = html + '<img src="'+base+'/'+title+'/thumbs/'+pic+'" class="psThumbImg" style="margin-bottom:5px;" onClick="loadImage(\s'psDisplay'+title+'\s',\s''+base+'/'+title+'/medium/'+pic+'\s');"\s/>';\n }\n \n e.innerHTML = html;\n } else { // not IE\n\n var psNav = createTiddlyElement(e,'div','psNav'+title,'psNav');\n \n var imgNavleft = createTiddlyElement(psNav,'img');\n imgNavleft.src = base + '/nav/left.gif';\n imgNavleft.align = 'left';\n imgNavleft.setAttribute("onmouseover", "moveThumbs('psThumbs"+title+"',5);");\n imgNavleft.setAttribute("onmouseout", "stopMove();");\n var imgNavright = createTiddlyElement(psNav,'img');\n imgNavright.src = base + '/nav/right.gif';\n imgNavright.align = 'right';\n imgNavright.setAttribute("onmouseover", "moveThumbs('psThumbs"+title+"',-5);");\n imgNavright.setAttribute("onmouseout", "stopMove();");\n \n var psThumbsWindow = createTiddlyElement(psNav,'div','psThumbsWindow'+title,'psThumbsWindow');\n var psThumbs = createTiddlyElement(psThumbsWindow,'div','psThumbs'+title,'psThumbs');\n psThumbs.style.left = '0px';\n \n for (var i=0; i<pics.length; i++) {\n var pic = pics[i];\n var img = createTiddlyElement(psThumbs,"img",null,'psThumbImg');\n img.src = base + '/' + title + '/thumbs/' + pic;\n img.setAttribute("onclick","loadImage('psDisplay" +title+ "', '" +base+ "/" +title+ "/medium/" +pic+ "');");\n }\n } // not IE\n\n var psDisplay = createTiddlyElement(e,'div','psDisplay'+title,'psDisplay');\n var imgDisplay = createTiddlyElement(psDisplay,'img');\n imgDisplay.src = base + '/' + title + '/medium/' + pics[0];\n\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n}\n)\n//}}}\n\n//{{{\n var move = 0;\n var curId;\n var curValX = 0;\n var curTime = 0;\n \n function moveThumbs(id,val) {\n curId = id;\n curValX = val;\n curTime = 50;\n \n move = 1;\n\n startMove();\n \n return;\n }\n \n function startMove() {\n if (move == 0) { return; }\n var e = document.getElementById(curId);\n var posX = e.style.left;\n posX = parseInt(posX);\n \n var max_size = e.offsetWidth\n \n var imgs = e.getElementsByTagName('img');\n var totalWidth = 0;\n for (var i=0; i < imgs.length; i++ ) {\n totalWidth = totalWidth + imgs[i].width + 24;\n }\n \n if ( (curValX>0) && (posX<0) ) { posX = posX + curValX; }\n if ( (curValX<0) && (posX > (max_size-totalWidth) ) ) { posX = posX + curValX; }\n e.style.left = posX + 'px';\n \n if (curTime>15) { curTime = curTime-1; }\n setTimeout("startMove()", curTime);\n return;\n \n }\n \n function stopMove() {\n move = 0;\n return;\n }\n\n function loadImage(id,pic) {\n var d = document.getElementById(id);\n var e = d.getElementsByTagName('img');\n e[0].src = pic;\n return;\n }\n//}}}\n// //===
<<minesweeper>>\n\nGet this [[Minesweeper]] plugin for your TiddlyWiki\n\nFeatures that might be coming:\n* proper graphics\n* remembering best times in a tiddler somewhere\n* nicer layout with less grey
/***\n|''Name:''|Plugin: Syntaxify|\n|''Description:''|Performs syntax highlighting on CSS, JavaScript, and HTML/XML|\n|''Version:''|1.1.0|\n|''Date:''|Aug 23, 2006|\n|''Source:''|http://bob.mcelrath.org/syntaxify.html|\n|''Author:''|BobMcElrath|\n|''Email:''|my first name at my last name dot org|\n|''License:''|[[GPL open source license|http://www.gnu.org/licenses/gpl.html]]|\n|''~CoreVersion:''|2.0.0|\n!Description\nThis plugin will syntax highlight ("pretty-print") source code used by TiddlyWiki. To activate CSS markup, enclose the code in the CSS code in the delimiters \n<html><code>\n/*{{{*/<br/>\n/* CSS code here */<br/>\n/*}}}*/<br/>\n</code></html>\nTo activate XML markup, enclose your HTML/XML in the delimiters\n<html><code>\n<!--{{{--><br/>\n<!-- XML/HTML code here --><br/>\n<!--}}}--><br/>\n</code></html>\nAnd to activate JavaScript markup, enclose your code in the delimiters\n<html><code>\n//{{{<br/>\n// JavaScript code here.<br/>\n//}}}<br/>\n</code></html>\n\nIn addition, all of the above languages can be syntaxified by using the custom class formatter\n<html><code>\n{{foo{<br/>\n code for language "foo" here<br/>\n}}}<br/>\n</code></html>\nwhere {{{foo}}} is the name of the language: {{{css}}}, {{{javascript}}}, or {{{xml}}}. This plugin can be extended with new languages by creating a data structure like those below (in {{{syntaxify.languages}}} and then calling {{{syntaxify.addLanguage}}}.\n!History\n* 1.1 Release\n** Rewrite things to make it easier to add new languages.\n** Override customClasses to syntaxify when the class corresponds to a known language.\n** TiddlyWiki 2.1 beta compatibility\n* 1.0.2 Release\n** Don't use {{{class}}} as a variable name, dummy.\n* 1.0.1 Release\n** Simplified stylesheet and removed line numbering.\n** Fixed highlighting when <html><code>*/</code></html> appeared at the beginning of a line.\n** Fixed blank lines not being shown if {{{list-style-type: none}}} was turned on.\n** Small speedups\n* 1.0.0 Initial Release\n!Code\n***/\n//{{{\nversion.extensions.Syntaxify = { major: 1, minor: 1, revision: 0, date: new Date("2006","08","23"),\n source: "http://bob.mcelrath.org/syntaxify.html"\n};\n\nvar syntaxify = {};\n\nsyntaxify.regexpSpace = new RegExp(" ", "mg");\nsyntaxify.regexpTab = new RegExp("\st", "mg");\nsyntaxify.regexpAmp = new RegExp("&","mg");\nsyntaxify.regexpLessThan = new RegExp("<","mg");\nsyntaxify.regexpGreaterThan = new RegExp(">","mg");\nsyntaxify.regexpQuote = new RegExp("\s"","mg");\nsyntaxify.regexpDoubleQuotedString = new RegExp("\s"(?:\s\s\s\s.|[^\s\s\s\s\s"])*?\s"", "mg");\nsyntaxify.regexpSingleQuotedString = new RegExp("'(?:\s\s\s\s.|[^\s\s\s\s'])*?'", "mg");\nsyntaxify.regexpCSingleLineComment = new RegExp('//.*$', "g");\nsyntaxify.regexpCMultiLineComment \n = new RegExp('/\s\s*(?:(?:.|(?:\s\sr)?\s\sn)(?!\s\s*/))*(?:.|(?:\s\sr)?\s\sn)?\s\s*/',"mg");\nString.prototype.htmlListMono = function() {\n return(this.replace(syntaxify.regexpAmp,"&")\n .replace(syntaxify.regexpLessThan,"<")\n .replace(syntaxify.regexpGreaterThan,">")\n .replace(syntaxify.regexpQuote,""")\n .replace(syntaxify.regexpSpace," ")\n .replace(syntaxify.regexpTab," "));\n}\n\nsyntaxify.handleSpanClass = function(w) {\n var match, lastPos=0;\n if(this.lookahead) {\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 createTiddlyText(w.output, lookaheadMatch[1]);\n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?lookaheadMatch[2].htmlListMono():lookaheadMatch[2];\n }\n } else {\n while((match = regexpNewLine.exec(w.matchText)) != null) { // multi-line\n var alt = "";\n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?w.matchText.substr(lastPos,match.index-lastPos).htmlListMono()\n :w.matchText.substr(lastPos,match.index-lastPos);\n if(w.output.className != "alt") alt = "alt";\n w.output = createTiddlyElement(w.output.parentNode, "li", null, alt);\n lastPos = match.index;\n } \n var e = createTiddlyElement(w.output, "span", null, this.name);\n e.innerHTML = this.hasSpaces?w.matchText.substr(lastPos, w.matchText.length-lastPos).htmlListMono()\n :w.matchText.substr(lastPos, w.matchText.length-lastPos)\n }\n}\n\n/* This is a shadow tiddler. Do not edit it here. Instead, open the tiddler StyleSheetSyntaxify \n * and edit it instead. (go to the toolbar on the right and select "More"->"Shadowed") */\nconfig.shadowTiddlers.StyleSheetSyntaxify = "/*{{{*/\sn"\n+".viewer div.syntaxify {\sn"\n+" font-family: 'Courier New' , Courier, mono;\sn"\n+" background-color: #ffc;\sn"\n+" border: 1px solid #fe8;\sn"\n+" padding: 0.5em;\sn"\n+" margin: 0 0 1em 0.5em;\sn"\n+" font-size: 1.2em;\sn"\n+" overflow: auto;\sn"\n+"}\sn\sn"\n+".syntaxify ol {\sn"\n+" margin: 0;\sn"\n+" padding: 1px;\sn"\n+" color: #2B91AF;\sn"\n+"}\sn\sn"\n+".syntaxify ol li {\sn"\n+" background-color: #ffc;\sn"\n+" color: black;\sn"\n+" list-style-type: none;\sn"\n+"/* An alternate style to enable line numbering -- remove the line above and uncomment below if desired */\sn"\n+"/*\sn"\n+" list-style-type: 1;\sn"\n+" border-left: 3px solid #fe8;\sn"\n+" margin-left: 3.5em;\sn"\n+"*/\sn"\n+"}\sn\sn"\n+".syntaxify ol li.alt { background-color: #ffe; }\sn\sn"\n+".syntaxify ol li span { color: black; }\sn"\n+".syntaxify .singleLineComments { color: green; }\sn"\n+".syntaxify .multiLineComments { color: green; }\sn"\n+".syntaxify .multiLineComments1 { color: red; }\sn"\n+".syntaxify .tag { font-weight: bold; color: blue; }\sn"\n+".syntaxify .tagname { font-weight: bold; color: black; }\sn"\n+".syntaxify .attribute { color: rgb(127,0,85); }\sn"\n+".syntaxify .value { color: rgb(42,0,255); }\sn"\n+".syntaxify .keywords { color: #006699; }\sn"\n+".syntaxify .keywords1 { color: red; }\sn"\n+".syntaxify .delimiters { color: maroon; }\sn"\n+".syntaxify .delimiters1 { color: olive; }\sn"\n+".syntaxify .literals { color: maroon; }\sn"\n+".syntaxify .literals1 { color: blue; }\sn"\n+".syntaxify .literals2 { color: blue; }\sn"\n+".syntaxify .literals3 { color: #129; }\sn"\n+".syntaxify .identifiers { font-weight: bold; color: blue; }\sn"\n+".syntaxify .identifiers1 { font-weight: bold; color: black; }\sn"\n+"/*}}}*/";\n\nstore.addNotification("StyleSheetSyntaxify",refreshStyles);\nconfig.shadowTiddlers.ViewTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.ViewTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.EditTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.EditTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.PageTemplate = "<!--{{{-->\sn"+config.shadowTiddlers.PageTemplate+"\sn<!--}}}-->";\nconfig.shadowTiddlers.StyleSheetPrint = "/*{{{*/\sn"+config.shadowTiddlers.StyleSheetPrint+"\sn/*}}}*/";\n\nsyntaxify.commonFormatters = [\n{ name: "spaces",\n match: "[ \s\st]+",\n handler: function(w) {\n //var e = createTiddlyElement(w.output, "span", null, null);\n //e.innerHTML = w.matchText.htmlListMono();\n //w.output.appendChild(document.createTextNode(w.matchText.htmlListMono()));\n w.output.innerHTML += w.matchText.htmlListMono();\n }\n},{ name: "newline",\n match: "\s\sn",\n handler: function(w) {\n var alt = ""\n if(w.output.className != "alt") alt = "alt";\n if(!w.output.hasChildNodes()) w.output.innerHTML = " ";\n w.output = createTiddlyElement(w.output.parentNode, "li", null, alt);\n }\n}];\n\nsyntaxify.xmlTagFormatters = syntaxify.commonFormatters;\nsyntaxify.xmlTagFormatters = syntaxify.xmlTagFormatters.concat([\n{ name: "tagname",\n match: '<[/\s\s?]?\s\ss*(?:[\s\sw-\s\s.]+)',\n lookahead: '(<[/\s\s?]?\s\ss*)([\s\sw-\s\s.]+)',\n handler: syntaxify.handleSpanClass\n},{\n name: "attribute-value",\n match: '[\s\sw-\s.]+(?:\s\ss*=\s\ss*"[^"]*?"|\s'[^\s']*?\s'|\s\sw+)?',\n lookahead: '([\s\sw-\s.]+)(?:(\s\ss*=\s\ss*)("[^"]*?"|\s'[^\s']*?\s'|\s\sw+))?',\n handler: function(w) {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg"); \n lookaheadRegExp.lastIndex = w.matchStart; \n var lookaheadMatch = lookaheadRegExp.exec(w.source); \n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { \n var e = createTiddlyElement(w.output, "span", null, "attribute");\n e.innerHTML = lookaheadMatch[1];\n if(lookaheadMatch[2]) {\n var e = createTiddlyElement(w.output, "span");\n e.innerHTML = lookaheadMatch[2].htmlListMono();\n e = createTiddlyElement(w.output, "span", null, "value");\n e.innerHTML = lookaheadMatch[3].htmlListMono();\n }\n }\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length; \n }\n}]);\n\n\n// A rather huge data structure to store languages. Add to it!\nsyntaxify.languages = {\njavascript: {\n singleLineComments: [[syntaxify.regexpCSingleLineComment.source]],\n multiLineComments: [[syntaxify.regexpCMultiLineComment.source]],\n keywords: [['abstract', 'boolean', 'break', 'byte', 'case', 'catch', 'char',\n 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do',\n 'double', 'else', 'enum', 'export', 'extends', 'false', 'final',\n 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements',\n 'import', 'in', 'instanceof', 'int', 'interface', 'long', 'native',\n 'new', 'null', 'package', 'private', 'protected', 'public', 'return',\n 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw',\n 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void',\n 'volatile', 'while', 'with']\n ],\n literals: [\n [syntaxify.regexpSingleQuotedString.source],\n [syntaxify.regexpDoubleQuotedString.source],\n ["\s\sb\s\sd+(?:\s\s.\s\sd+(?:[eE][\s\s+-]\s\sd+)?)?\s\sb"] // Numbers\n ],\n delimiters: [["[\s\s{\s\s}]"],["[\s\s(\s\s)]"],["[\s\s[\s\s]]"]]\n}, \ncss: {\n multiLineComments: [[syntaxify.regexpCSingleLineComment.source]],\n keywords: [\n // Keywords appearing on the LHS of expressions\n ['ascent', 'azimuth', 'background-attachment', 'background-color',\n 'background-image', 'background-position', 'background-repeat',\n 'background', 'baseline', 'bbox', 'border-collapse', 'border-color',\n 'border-spacing', 'border-style', 'border-top', 'border-right',\n 'border-bottom', 'border-left', 'border-top-color',\n 'border-right-color', 'border-bottom-color', 'border-left-color',\n 'border-top-style', 'border-right-style', 'border-bottom-style',\n 'border-left-style', 'border-top-width', 'border-right-width',\n 'border-bottom-width', 'border-left-width', 'border-width', 'border',\n 'bottom', 'cap-height', 'caption-side', 'centerline', 'clear', 'clip',\n 'color', 'content', 'counter-increment', 'counter-reset', 'cue-after',\n 'cue-before', 'cue', 'cursor', 'definition-src', 'descent',\n 'direction', 'display', 'elevation', 'empty-cells', 'float',\n 'font-size-adjust', 'font-family', 'font-size', 'font-stretch',\n 'font-style', 'font-variant', 'font-weight', 'font', 'height', 'left',\n 'letter-spacing', 'line-height', 'list-style-image',\n 'list-style-position', 'list-style-type', 'list-style', 'margin-top',\n 'margin-right', 'margin-bottom', 'margin-left', 'margin',\n 'marker-offset', 'marks', 'mathline', 'max-height', 'max-width',\n 'min-height', 'min-width', 'orphans', 'outline-color',\n 'outline-style', 'outline-width', 'outline', 'overflow', 'padding-top',\n 'padding-right', 'padding-bottom', 'padding-left', 'padding', 'page',\n 'page-break-after', 'page-break-before', 'page-break-inside', 'pause',\n 'pause-after', 'pause-before', 'pitch', 'pitch-range', 'play-during',\n 'position', 'quotes', 'richness', 'right', 'size', 'slope', 'src',\n 'speak-header', 'speak-numeral', 'speak-punctuation', 'speak',\n 'speech-rate', 'stemh', 'stemv', 'stress', 'table-layout',\n 'text-align', 'text-decoration', 'text-indent', 'text-shadow',\n 'text-transform', 'unicode-bidi', 'unicode-range', 'units-per-em',\n 'vertical-align', 'visibility', 'voice-family', 'volume',\n 'white-space', 'widows', 'width', 'widths', 'word-spacing', 'x-height',\n 'z-index'],\n // Treat !important as a different kind of keyword\n ["important"]\n ],\n literals: [\n // Literals appearing on the RHS of expressions\n ['above', 'absolute', 'all', 'always', 'aqua', 'armenian', 'attr',\n 'aural', 'auto', 'avoid', 'baseline', 'behind', 'below',\n 'bidi-override', 'black', 'blink', 'block', 'blue', 'bold', 'bolder',\n 'both', 'bottom', 'braille', 'capitalize', 'caption', 'center',\n 'center-left', 'center-right', 'circle', 'close-quote', 'code',\n 'collapse', 'compact', 'condensed', 'continuous', 'counter',\n 'counters', 'crop', 'cross', 'crosshair', 'cursive', 'dashed',\n 'decimal', 'decimal-leading-zero', 'default', 'digits', 'disc',\n 'dotted', 'double', 'embed', 'embossed', 'e-resize', 'expanded',\n 'extra-condensed', 'extra-expanded', 'fantasy', 'far-left',\n 'far-right', 'fast', 'faster', 'fixed', 'format', 'fuchsia', 'gray',\n 'green', 'groove', 'handheld', 'hebrew', 'help', 'hidden', 'hide',\n 'high', 'higher', 'icon', 'inline-table', 'inline', 'inset', 'inside',\n 'invert', 'italic', 'justify', 'landscape', 'large', 'larger',\n 'left-side', 'left', 'leftwards', 'level', 'lighter', 'lime',\n 'line-through', 'list-item', 'local', 'loud', 'lower-alpha',\n 'lowercase', 'lower-greek', 'lower-latin', 'lower-roman', 'lower',\n 'low', 'ltr', 'marker', 'maroon', 'medium', 'message-box', 'middle',\n 'mix', 'move', 'narrower', 'navy', 'ne-resize', 'no-close-quote',\n 'none', 'no-open-quote', 'no-repeat', 'normal', 'nowrap', 'n-resize',\n 'nw-resize', 'oblique', 'olive', 'once', 'open-quote', 'outset',\n 'outside', 'overline', 'pointer', 'portrait', 'pre', 'print',\n 'projection', 'purple', 'red', 'relative', 'repeat', 'repeat-x',\n 'repeat-y', 'ridge', 'right', 'right-side', 'rightwards', 'rtl',\n 'run-in', 'screen', 'scroll', 'semi-condensed', 'semi-expanded',\n 'separate', 'se-resize', 'show', 'silent', 'silver', 'slower', 'slow',\n 'small', 'small-caps', 'small-caption', 'smaller', 'soft', 'solid',\n 'speech', 'spell-out', 'square', 's-resize', 'static', 'status-bar',\n 'sub', 'super', 'sw-resize', 'table-caption', 'table-cell',\n 'table-column', 'table-column-group', 'table-footer-group',\n 'table-header-group', 'table-row', 'table-row-group', 'teal',\n 'text-bottom', 'text-top', 'thick', 'thin', 'top', 'transparent',\n 'tty', 'tv', 'ultra-condensed', 'ultra-expanded', 'underline',\n 'upper-alpha', 'uppercase', 'upper-latin', 'upper-roman', 'url',\n 'visible', 'wait', 'white', 'wider', 'w-resize', 'x-fast', 'x-high',\n 'x-large', 'x-loud', 'x-low', 'x-slow', 'x-small', 'x-soft',\n 'xx-large', 'xx-small', 'yellow'],\n // Font literals\n ['[mM]ono(?:space)?', '[tT]ahoma', '[vV]erdana', '[aA]rial',\n '[hH]elvetica', '[sS]ans(?:-serif)?', '[sS]erif', '[Cc]ourier'],\n // Measurement literals\n ["\s\sb\s\sd+(?:\s\s.\s\sd+)?(?:em|pt|px|cm|in|pc|mm)\s\sb"],\n // Color literals\n ['(?:\s\s#[a-fA-F0-9]{6}\s\sb|\s\s#[a-fA-F0-9]{3}\s\sb|rgb\s\s(\s\ss*\s\sd+\s\ss*,\s\ss*\s\sd+\s\ss*,\s\ss*\s\sd+\s\ss*\s\s))']\n ],\n identifiers: [["\s\s.[a-zA-Z_]\s\sw*"],["\s\s#[a-zA-Z_]\s\sw*"]],\n delimiters: [["[\s\s{\s\s}]"]]\n}, \nxml: {\n multiLineComments: [\n ["<[^!>]*!--\s\ss*(?:(?:.|(?:\s\sr)?\s\sn)(?!--))*?(?:(?:.|(?:\s\sr)?\s\sn)(?=--))?\s\ss*--[^>]*?>"],\n ['<\s\s!\s\s[[\s\sw\s\ss]*?\s\s[(?:(?:.|(?:\s\sr)?\s\sn)(?!\s\s]\s\s]>))*?(?:(?:.|(?:\s\sr)?\s\sn)(?=\s\s]\s\s]>))?\s\s]\s\s]>']\n ],\n customFormatters: [{\n name: "tag",\n match: "<[/\s\s?]?[^>]*?>",\n handler: function(w) {\n var formatter = new Formatter(syntaxify.xmlTagFormatters);\n var wikifier = new Wikifier(w.matchText, formatter, w.highlightRegExp, w.output);\n wikifier.subWikify(w.output, null);\n }\n }]\n}};\nconfig.formatterHelpers.monospacedByLineHelper = function(w) { \n var lookaheadRegExp = (typeof(this.lookaheadRegExp) == "undefined")?(new RegExp(this.lookahead,"mg")):this.lookaheadRegExp;\n lookaheadRegExp.lastIndex = w.matchStart; \n var lookaheadMatch = lookaheadRegExp.exec(w.source); \n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { \n var text = lookaheadMatch[1]; \n if(config.browser.isIE) text = text.replace(/\sn/g,"\sr"); \n if(this.formatters) {\n var d = createTiddlyElement(w.output,"div",null,"syntaxify "+this.language);\n var l = createTiddlyElement(d,"ol");\n var li = createTiddlyElement(l,"li");\n li.autoLinkWikiWords = function() { return false; }; // 2.1 weirdism\n var formatter = new Formatter(this.formatters);\n var wikifier = new Wikifier(text, formatter, w.highlightRegExp, li);\n wikifier.subWikify(li, null);\n if(!l.childNodes[l.childNodes.length-1].hasChildNodes())\n l.removeChild(l.childNodes[l.childNodes.length-1]);\n } else { \n var e = createTiddlyElement(w.output,"pre",null,null,text); \n } \n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length; \n } \n} \nconfig.formatterHelpers.customClassesHelper = function(w) {\n var lookaheadRegExp = (typeof(this.lookaheadRegExp) == "undefined")?(new RegExp(this.lookahead,"mg")):this.lookaheadRegExp;\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source);\n if(lookaheadMatch)\n {\n var isByLine = lookaheadMatch[2] == "\sn";\n var p = createTiddlyElement(w.output,isByLine ? "div" : "span",null,lookaheadMatch[1]);\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n if(isByLine && typeof(syntaxify.formatters[lookaheadMatch[1]]) != "undefined") {\n var d = createTiddlyElement(w.output,"div",null,"syntaxify "+lookaheadMatch[1]);\n var l = createTiddlyElement(d,"ol");\n var li = createTiddlyElement(l,"li");\n li.autoLinkWikiWords = function() { return false; }; // 2.1 weirdism\n var formatter = new Formatter(syntaxify.formatters[lookaheadMatch[1]]);\n var terminatorRegExp = new RegExp(this.terminator,"mg");\n terminatorRegExp.lastIndex = w.nextMatch;\n var terminatorMatch = terminatorRegExp.exec(w.source);\n var text = w.source.substr(w.nextMatch, terminatorMatch.index-w.nextMatch);\n var wikifier = new Wikifier(text, formatter, w.highlightRegExp, li);\n wikifier.subWikify(li, null);\n if(!l.childNodes[l.childNodes.length-1].hasChildNodes())\n l.removeChild(l.childNodes[l.childNodes.length-1]);\n w.nextMatch = terminatorMatch.index+terminatorMatch[0].length;\n } else {\n w.subWikify(p,this.terminator);\n }\n }\n}\n\nsyntaxify.formatters = {};\n\nsyntaxify.addLanguages = function(languages) {\n for(lang in languages) {\n syntaxify.formatters[lang] = new Array();\n for(var i=0;i<syntaxify.commonFormatters.length;i++)\n syntaxify.formatters[lang].push(syntaxify.commonFormatters[i]);\n var addSpanClass = function(rule, spaces, wordbreak) {\n if(typeof(languages[lang][rule]) != "undefined") {\n for(var j=0;j<languages[lang][rule].length;j++) {\n syntaxify.formatters[lang].push({\n name: rule+((j==0)?"":j),\n match: wordbreak?("(?:\s\sb"+languages[lang][rule][j].join("\s\sb|\s\sb")+"\s\sb)")\n :("(?:"+languages[lang][rule][j].join("|")+")"),\n hasSpaces: spaces,\n handler: syntaxify.handleSpanClass\n });\n }\n }\n };\n addSpanClass("singleLineComments", true, false);\n addSpanClass("multiLineComments", true, false);\n addSpanClass("keywords", false, true);\n addSpanClass("literals", true, false);\n addSpanClass("delimiters", false, false);\n addSpanClass("identifiers", false, false);\n if(typeof(languages[lang].customFormatters) != "undefined") \n syntaxify.formatters[lang] = syntaxify.formatters[lang].concat(languages[lang].customFormatters);\n }\n}\n\nsyntaxify.addLanguages(syntaxify.languages);\n\n// Override the several built-in TiddlyWiki language-specific <pre> formatters\nfor(var i=0;i<config.formatters.length;i++) { \n if(config.formatters[i].name == "monospacedByLineForPlugin") { \n config.formatters[i].language = "javascript";\n config.formatters[i].formatters = syntaxify.formatters["javascript"];\n config.formatters[i].handler = config.formatterHelpers.monospacedByLineHelper; \n } \n if(config.formatters[i].name == "monospacedByLineForCSS") { \n config.formatters[i].language = "css";\n config.formatters[i].formatters = syntaxify.formatters["css"];\n config.formatters[i].handler = config.formatterHelpers.monospacedByLineHelper; \n } \n if(config.formatters[i].name == "monospacedByLineForTemplate") { \n config.formatters[i].language = "xml";\n config.formatters[i].formatters = syntaxify.formatters["xml"]; \n config.formatters[i].handler = config.formatterHelpers.monospacedByLineHelper; \n } \n if(config.formatters[i].name == "customClasses") {\n config.formatters[i].handler = config.formatterHelpers.customClassesHelper; \n config.formatters[i].terminator = "\s\s}\s\s}\s\s}\sn?"; \n }\n} \n\n//}}}
/***\n| Name:|QuickOpenTagPlugin|\n| Description:|Changes tag links to make it easier to open tags as tiddlers|\n| Version:|6.1.1|\n| Date:|01-Oct-2006|\n| Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\n***/\n//{{{\nconfig.quickOpenTag = {\n\n dropdownChar: (document.all ? "\su25bc" : "\su25be"), // the little one doesn't work in IE\n\n createTagButton: function(place,tag,excludeTiddler) {\n // little hack so we can to <<tag PrettyTagName|RealTagName>>\n var splitTag = tag.split("|");\n var pretty = tag;\n if (splitTag.length == 2) {\n tag = splitTag[1];\n pretty = splitTag[0];\n }\n \n var sp = createTiddlyElement(place,"span",null,"quickopentag");\n createTiddlyText(createTiddlyLink(sp,tag,false),pretty);\n \n var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,\n config.views.wikified.tag.tooltip.format([tag]),onClickTag);\n theTag.setAttribute("tag",tag);\n if (excludeTiddler)\n theTag.setAttribute("tiddler",excludeTiddler);\n return(theTag);\n },\n\n miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var tagged = store.getTaggedTiddlers(tiddler.title);\n if (tagged.length > 0) {\n var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,\n config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);\n theTag.setAttribute("tag",tiddler.title);\n theTag.className = "miniTag";\n }\n },\n\n allTagsHandler: function(place,macroName,params) {\n var tags = store.getTags();\n var theDateList = createTiddlyElement(place,"ul");\n if(tags.length == 0)\n createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);\n for (var t=0; t<tags.length; t++) {\n var theListItem = createTiddlyElement(theDateList,"li");\n var theLink = createTiddlyLink(theListItem,tags[t][0],true);\n var theCount = " (" + tags[t][1] + ")";\n theLink.appendChild(document.createTextNode(theCount));\n var theDropDownBtn = createTiddlyButton(theListItem," " +\n config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);\n theDropDownBtn.setAttribute("tag",tags[t][0]);\n }\n },\n\n // todo fix these up a bit\n styles: \n"/*{{{*/\sn"+\n"/* created by QuickOpenTagPlugin */\sn"+\n".tagglyTagged .quickopentag, .tagged .quickopentag \sn"+\n" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }\sn"+\n".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }\sn"+\n".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}\sn"+\n"/* extra specificity to make it work right */\sn"+\n"#displayArea .viewer .quickopentag a.button, \sn"+\n"#displayArea .viewer .quickopentag a.tiddyLink, \sn"+\n"#mainMenu .quickopentag a.tiddyLink, \sn"+\n"#mainMenu .quickopentag a.tiddyLink \sn"+\n" { border:0px solid black; }\sn"+\n"#displayArea .viewer .quickopentag a.button, \sn"+\n"#mainMenu .quickopentag a.button \sn"+\n" { margin-left:0px; padding-left:2px; }\sn"+\n"#displayArea .viewer .quickopentag a.tiddlyLink, \sn"+\n"#mainMenu .quickopentag a.tiddlyLink \sn"+\n" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }\sn"+\n"a.miniTag {font-size:150%;} \sn"+\n"#mainMenu .quickopentag a.button \sn"+\n" /* looks better in right justified main menus */\sn"+\n" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }\sn" + \n"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }\sn" +\n"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }\sn" +\n"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }\sn" +\n"/*}}}*/\sn"+\n "",\n\n init: function() {\n // we fully replace these builtins. can't hijack them easily\n window.createTagButton = this.createTagButton;\n config.macros.allTags.handler = this.allTagsHandler;\n config.macros.miniTag = { handler: this.miniTagHandler };\n config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;\n if (store)\n store.addNotification("QuickOpenTagStyles",refreshStyles);\n else\n config.notifyTiddlers.push({name:"QuickOpenTagStyles", notify: refreshStyles});\n }\n\n}\n\nconfig.quickOpenTag.init();\n\n//}}}\n
http://www.antsight.com/zsl/rainbowcrack/
/***\n|''Name:''|RearrangeTiddlersPlugin|\n|''Source:''|http://www.TiddlyTools.com/#AttachFilePlugin|\n|''Author:''|Joe Raii|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0.10|\n\nadapted from: http://www.cs.utexas.edu/~joeraii/dragn/#Draggable\nchanges by ELS:\n* hijack refreshTiddler() instead of overridding createTiddler()\n* find title element by className instead of elementID\n* set cursor style via code instead of stylesheet\n* set tooltip help text\n* set tiddler "position:relative" when starting drag event, restore saved value when drag ends\n* update 2006.08.07: use getElementsByTagName("*") to find title element, even when it is 'buried' deep in tiddler DOM elements (due to custom template usage)\n\n***/\n//{{{\n\nStory.prototype.rearrangeTiddlersHijack_refreshTiddler = Story.prototype.refreshTiddler;\nStory.prototype.refreshTiddler = function(title,template,unused1,unused2,unused3,unused4,unused5)\n{\n this.rearrangeTiddlersHijack_refreshTiddler(title,template,unused1,unused2,unused3,unused4,unused5);\n var theTiddler = document.getElementById(this.idPrefix + title); if (!theTiddler) return;\n var theHandle;\n var children=theTiddler.getElementsByTagName("*");\n for (var i=0; i<children.length; i++) if (hasClass(children[i],"title")) { theHandle=children[i]; break; }\n if (!theHandle) return theTiddler;\n\n Drag.init(theHandle, theTiddler, 0, 0, null, null);\n theHandle.style.cursor="move";\n theHandle.title="drag title to re-arrange tiddlers"\n theTiddler.onDrag = function(x,y,myElem) {\n if (this.style.position!="relative")\n { this.savedstyle=this.style.position; this.style.position="relative"; }\n y = myElem.offsetTop;\n var next = myElem.nextSibling;\n var prev = myElem.previousSibling;\n if (next && y + myElem.offsetHeight > next.offsetTop + next.offsetHeight/2) { \n myElem.parentNode.removeChild(myElem);\n next.parentNode.insertBefore(myElem, next.nextSibling);//elems[pos+1]);\n myElem.style["top"] = -next.offsetHeight/2+"px";\n }\n if (prev && y < prev.offsetTop + prev.offsetHeight/2) { \n myElem.parentNode.removeChild(myElem);\n prev.parentNode.insertBefore(myElem, prev);\n myElem.style["top"] = prev.offsetHeight/2+"px";\n }\n };\n theTiddler.onDragEnd = function(x,y,myElem) {\n myElem.style["top"] = "0px";\n if (this.savedstyle!=undefined)\n this.style.position=this.savedstyle;\n }\n return theTiddler;\n}\n\n/**************************************************\n * dom-drag.js\n * 09.25.2001\n * www.youngpup.net\n **************************************************\n * 10.28.2001 - fixed minor bug where events\n * sometimes fired off the handle, not the root.\n **************************************************/\n\nvar Drag = {\n obj:null,\n\n init:\n function(o, oRoot, minX, maxX, minY, maxY) {\n o.onmousedown = Drag.start;\n o.root = oRoot && oRoot != null ? oRoot : o ;\n if (isNaN(parseInt(o.root.style.left))) o.root.style.left="0px";\n if (isNaN(parseInt(o.root.style.top))) o.root.style.top="0px";\n o.minX = typeof minX != 'undefined' ? minX : null;\n o.minY = typeof minY != 'undefined' ? minY : null;\n o.maxX = typeof maxX != 'undefined' ? maxX : null;\n o.maxY = typeof maxY != 'undefined' ? maxY : null;\n o.root.onDragStart = new Function();\n o.root.onDragEnd = new Function();\n o.root.onDrag = new Function();\n },\n\n start:\n function(e) {\n var o = Drag.obj = this;\n e = Drag.fixE(e);\n var y = parseInt(o.root.style.top);\n var x = parseInt(o.root.style.left);\n o.root.onDragStart(x, y, Drag.obj.root);\n o.lastMouseX = e.clientX;\n o.lastMouseY = e.clientY;\n if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;\n if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;\n if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;\n if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;\n document.onmousemove = Drag.drag;\n document.onmouseup = Drag.end;\n Drag.obj.root.style["z-index"] = "10";\n return false;\n },\n\n drag:\n function(e) {\n e = Drag.fixE(e);\n var o = Drag.obj;\n var ey = e.clientY;\n var ex = e.clientX;\n var y = parseInt(o.root.style.top);\n var x = parseInt(o.root.style.left);\n var nx, ny;\n if (o.minX != null) ex = Math.max(ex, o.minMouseX);\n if (o.maxX != null) ex = Math.min(ex, o.maxMouseX);\n if (o.minY != null) ey = Math.max(ey, o.minMouseY);\n if (o.maxY != null) ey = Math.min(ey, o.maxMouseY);\n nx = x + (ex - o.lastMouseX);\n ny = y + (ey - o.lastMouseY);\n Drag.obj.root.style["left"] = nx + "px";\n Drag.obj.root.style["top"] = ny + "px";\n Drag.obj.lastMouseX = ex;\n Drag.obj.lastMouseY = ey;\n Drag.obj.root.onDrag(nx, ny, Drag.obj.root);\n return false;\n },\n\n end:\n function() {\n document.onmousemove = null;\n document.onmouseup = null;\n Drag.obj.root.style["z-index"] = "0";\n Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style["left"]), parseInt(Drag.obj.root.style["top"]), Drag.obj.root);\n Drag.obj = null;\n },\n\n fixE:\n function(e) {\n if (typeof e == 'undefined') e = window.event;\n if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;\n if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;\n return e;\n }\n};\n//}}}\n
This method should work for most 1394/Firewire enabled tuners. It has been tested on the Mitsubishi Integrated TV's, SA3250HD, Motorola 620X (with firmware 7.10 or higher), and the Samsung T165. *Please list your tests and I will update* This method will not allow you to capture 5C encrypted content, *see below for details* This method captures the original Transport stream sent by your provider, so if it is sent with DD 5.1 then you will capture DD5.1. This method only works with Digital channels, analogue cable channels will not work.\n\nYou will need some drivers. Follow the link and Download firewire.zip and unzip.\nIf the link is bad PM me and I will fix it.\nFirst device drivers. There are more MCE specific items included in the package, if you are using using XP then you only need the driver. You may also want to play with the channel changing software, which works on both XP and MCE.\nhttp://www.accidentsworld.com/tgb/firestb.zip\n\nThere are a few pieces of software that I know of that can capture using these drivers, Capdvhs, DCTrecord and MCE using the included software.\nhttp://www.yamabe.org/soft/CapDVHS0306e.zip\nhttp://home.comcast.net/~brzez2/dctrecord.html\n\nNow that you have everything you need.\nAfter unzipping firestb.msi run and if you are using MCE install the components you want. If you are running XP then at the very least install the "Firewire Drivers" component, you won't be able to double click on it, you will have to use a different command to skip the MCE required screen. Now you can just choose the driver. \n\nCode:\nMSIEXEC /i firestb.msi IDENT=0\n\n\nClick continue anyway a the signed driver screen.\n\nPlug in the 1394 cable.\nFound new hardware wizard will come up.\n\nKeep hitting cancel until you see "Tuner AV/C Device" or "Tuner AV/C Panel" as the hardware that was found. Install both like any other device.\nThen Choose Install the software automatically (Recommended).\nClick Next\nKeep clicking Next.\nThen click Finished.\n\nClick cancel on any other devices that are automatically detected.\nI would go back into Device manager and disable the other devices so windows doesn't keep looking for drivers on reboot.\n\nNow open CAPDVHS and a device should be listed under capture device.\n\nUnder settings I have the following boxes checked.\nConvert 188 bytes\nCheck PTS\nDelete to SyncByte\n\nI use .ts for all my file extensions and I left the file name format to the default.\n\nSelect the "Data Info." tab and hit the "Rec" Button. \nYou should see the info populated. \nHit stop and check your file. \nElecard works well for playback or Sasem OnAir Editor or VLC \nor http://theatertek.com/\nTo play with zoomplayer check this thread.\nhttp://www.avsforum.com/avs-vb/show...threadid=395039\n\n**Now you change the channel via 1394 and use with MCE see the readme for complete directions.\nhttp://www.thegreenbutton.com/commu...essageID=104152\n\n**Attention this is a recording thread. For playback issues please check out the home theater PC forum . **\nFor conversion help check out this guide.\nhttp://replayguide.sourceforge.net/dct6412/index.html\nThe files captured from this process are the same as from most HD PC recording techniques and playback issues are the same. Please don't post in here asking how to get smooth playback. There are plenty of discussions in the correct area on that topic. Also please don't ask how to convert to DVD, or any other conversion question. There are plenty of thread dedicated to that topic also. This thread is already too long to read, and I appreciate everyone helping out by staying on topic.\n\n**Added 5/26/04 **\nTo watch live HD without capturing first. \nOpen VLC v7.2 *might work with other versions.\nChoose "File" > "Open Capture Device"\n\nTo the right of "Video device name" click "Refresh List" Then choose "Panasonic MPEG2TS Tape Sub" from the drop down.\nClick "OK"\n\nJust a word of advice if I hit "Configure" or "Advanced Options" It blue screens my computer.\nThis seems to be much more resource intensive than watching a captured file. My AMD 2600 works at ~83% if I don't resize or any other effect. Any effect drives it to 100%. \n\nYou can also setup a shortcut to run VLC with the parms for picking up the stream automatically.\n\nTarget:\n\n"C:\sProgram Files\sVideoLAN\sVLC\svlc.exe" "dshow:// :dshow-vdev="Panasonic MPEG2TS Tape Subunit Device" :dshow-adev="" :dshow-size="" :no-dshow-config "\n\nStart In:\n\n"C:\sProgram Files\sVideoLAN\sVLC"\n*Thanks to E Jackson*\n\nTroubleshooting\n\nIf you can't load the driver, go over the directions again and again, make sure you don't miss any steps. It does require you to force XP to accept the drivers. \n\nIf the driver is loaded but the files are 0bytes after recording. Then you may have the driver loaded improperly or your cable company may have copy protection(5C) enabled. Try a different channel or search the original thread for someone who lives near you to see if they are having the same problem. You may also be able to reboot the Tuner. It is impossible to record content marked copy once, because it is protected from multiple copies. Typically if your provider is encrypting, than the only channels you would be able to record are the channels that are also available over the air. \n\n**Added 2/6/06**\nChanged drivers to the above. Added channel chaning support.\n\n**Added 3/18/05**\nIf you have XP SP2 and you can't get it to work see this post.\nhttp://www.avsforum.com/avs-vb/show...313#post5315313\n\n**Added 2/22/05**\nIf you have a Motorola 620x Check this post to see if that channel is 5C protected. http://www.avsforum.com/avs-vb/show...086#post3855086 \n\nIf you have a SA DVR with Passport \nhttp://www.avsforum.com/avs-vb/show...480#post4617480\n\nIf you have a SA DVR with SARA\nhttp://www.avsforum.com/avs-vb/show...067#post4613067\n\nYou may also have the wrong firmware version for the Motorola 620x, to check this.\nTo check firmware on Moto 6200:\nMenu- Setup- Cable Box- See Configuration- one of the entries on that page is Firmware. * Thanks drbenson*\n\nIf you are using a Motorola 620X with an older firmware you may need to replace your Meitape.inf from the zip file with this one. Try the original one first.\nhttp://www-personal.umich.edu/~bala...les/Meitape.inf\n\nIf you need help getting your OTA antenna to work check out.\nhttp://www.hdbeat.com/2006/01/30/ota-hd-demystified/\nIf you are looking for more sources for HD check this out.\nhttp://www.hdbeat.com/2006/02/20/ho...ing-on-your-pc/\nFor help connecting your pc to your hdtv check out.\nhttp://www.hdbeat.com/2006/02/08/ho...c-to-your-hdtv/\n\nThis is V.03 of this document please post corrections and suggestions.\n\nI hope this makes it easier .\n
[[Life Hacker|http://www.lifehacker.com/]]\n[[The Multitasking Myth|http://www.codinghorror.com/blog/archives/000691.html]]\n[[Software Development: It's a Religion|http://www.codinghorror.com/blog/archives/000699.html]]\n
You can grab me by the title, and drag me around. Baby.\n\nAlternatively, dragn can be used as a plugin. Just copy the [[Draggable]] tiddler, and tag it with systemConfig. Then add the [[StyleSheet]] entries to your style sheet. Not pretty yet, but easy to install. Does not work in Safari.\n\nA pretty implementation, with folding, can be seen here: [[siglet|http://www.cs.utexas.edu/~joeraii/siglet]]
/***\n| Name:|RenameTagsPlugin|\n| Description:|Allows you to easily rename or delete tags across multiple tiddlers|\n| Version:|6.9.3|\n| Date:|30-Sep-2006|\n| Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\nRename a tag and you will be prompted to rename it in all its tagged tiddlers.\n***/\n//{{{\nconfig.renameTags = {\n\n prompts: {\n rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",\n remove: "Remove the tag '%0' from %1 tidder%2?"\n },\n\n removeTag: function(tag,tiddlers) {\n for (var i=0;i<tiddlers.length;i++) {\n store.setTiddlerTag(tiddlers[i].title,false,tag);\n }\n },\n\n renameTag: function(oldTag,newTag,tiddlers) {\n for (var i=0;i<tiddlers.length;i++) {\n store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old\n store.setTiddlerTag(tiddlers[i].title,true,newTag); // add new\n }\n },\n\n storeMethods: {\n\n saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,\n\n saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields) {\n if (title != newTitle) {\n var tagged = this.getTaggedTiddlers(title);\n if (tagged.length > 0) {\n // then we are renaming a tag\n if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))\n config.renameTags.renameTag(title,newTitle,tagged);\n\n if (!this.tiddlerExists(title) && newBody == "")\n // dont create unwanted tiddler\n return null;\n }\n }\n return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields);\n },\n\n removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,\n\n removeTiddler: function(title) {\n var tagged = this.getTaggedTiddlers(title);\n if (tagged.length > 0)\n if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))\n config.renameTags.removeTag(title,tagged);\n return this.removeTiddler_orig_renameTags(title);\n }\n\n },\n\n init: function() {\n merge(TiddlyWiki.prototype,this.storeMethods);\n }\n}\n\nconfig.renameTags.init();\n\n//}}}\n\n
One more tip: \nGSSAPIAuthentication takes time during initial connection. Set it to "no" in the sshd_config and connections will speed up some.\n\nExample ~/.ssh/config showing how to customize ssh connections by host\n{{{\nHost forwardpop\nHostname shell.example.com\nLocalForward 9110 mail.example.com:110\nForwardAgent yes\nHost remotehost\nForwardX11 yes\nUser remoteuser\nHost *\nForwardX11 no\n}}}\nFinally, a command similar to LocalForward, called RemoteForward, forwards a port from the computer to which you are connected, to your computer. Please read the ssh_config man pages to find out how.\n\nTurn on compression with ssh -C or put Compression yes in your config file.\n\nAnother speed tweak involves changing your encryption cipher. The default cipher on many older systems is triple DES (3DES), which is slower than Blowfish and AES. New versions of OpenSSH default to Blowfish. You can change the cipher to blowfish with ssh -c blowfish.\nCipher changes to your config file depend on whether you are connecting with SSH1 or SSH2. For SSH1, use Cipher blowfish; for SSH2, use: Garrick, use a small font so the line below will fit on one line\n{{{\nCiphers blowfish-cbc,aes128-cbc,3des-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc\n}}}\n
Here are some examples that show the usage of the scriptClause in the ForEachTiddlerMacro.\n\n<<forEachTiddler\n where\n 'tiddler.tags.contains("scriptClauseExample")'\n>>\n\nSee also ForEachTiddlerExamples.
/***\n|''Name:''|SettingsPlugin|\n|''Version:''|1.1.0 (2006-07-30)|\n|''Type:''|plugin|\n|''Source:''|http://tiddlywiki.abego-software.de/#SettingsPlugin|\n|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|\n|''Documentation:''|[[SettingsPlugin Documentation]]|\n|''~SourceCode:''|[[SettingsPlugin SourceCode]]|\n|''Licence:''|[[BSD open source license (abego Software)]]|\n|''~CoreVersion:''|2.0.7|\n|''Browser:''|Firefox 1.5.0.2 or better; Internet Explorer 6.0|\n^^This tiddler contains compressed source code. [[Full Source Code|SettingsPlugin SourceCode]].^^\n***/\n// /%\nif(!version.extensions.SettingsPlugin){if(version.major<2){(function(){var s="Use TiddlyWiki 2.0 or better to run the Settings Plugin.";alert(s);throw s;})();}version.extensions.SettingsPlugin={major:1,minor:1,revision:0,date:new Date(2006,6,30),type:"plugin",source:"http://tiddlywiki.abego-software.de/#SettingsPlugin",documentation:"[[SettingsPlugin Documentation]]",sourcecode:"[[SettingsPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",coreVersion:"2.0.7",browser:"Firefox 1.5.0.2 or better; Internet Explorer 6.0"};if(!window.abego){window.abego={};}if(!abego.setTiddlerText){abego.setTiddlerText=function(_2,_3,_4,_5,_6,_7){var _8=_2.getTiddler(_3);if(_8&&(_8.text==_4)){return;}var _9=config.options.chkForceMinorUpdate;var _a=!_8?_5:_8.tags;_2.suspendNotifications();try{_2.saveTiddler(_3,_3,_4,_9?undefined:config.options.txtUserName,_9?undefined:new Date(),_a);}finally{_2.resumeNotifications();}if(_7){_2.notify(_3,true);}if(!_6&&config.options.chkAutoSave){saveChanges();}};}(function(){var _b="PrivateSettings";var _c="chkUsePrivateSettings";var _d="chkMakeSettingPrivateWhenChanged";var _e=null;var _f=false;var _10=function(_11,s){var _13=s.split(";");var _14={};for(var c=0;c<_13.length;c++){var p=_13[c].indexOf("=");if(p!=-1){var _17=_13[c].substr(0,p).trim();var _18=_13[c].substr(p+1).trim();_11[_17]=unescape(_18);_14[_17]=true;}}return _14;};var _19=function(_1a){var s=store.getTiddlerText(_b);_e=s?_10(_1a,s):{};};var _1c=function(_1d){_10(_1d,document.cookie);};var _1e=function(){var _1f={};_1c(_1f);return _1f;};var _20=function(){var _21={};_19(_21);return _21;};var _22=function(_23,_24){document.cookie=_23+"="+escape(_24)+"; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";};var _25=function(_26,s,_28){var _29=_20();if(s===null){if(!_e[_26]){return;}delete _29[_26];delete _e[_26];}else{var _2a=_29[_26];if(_2a!==undefined&&_2a==s){return;}_29[_26]=s;_e[_26]=true;}var t="";for(var i in _29){if(t){t+="; ";}t+=i+"="+escape(_29[i]);}abego.setTiddlerText(store,_b,t,["excludeLists","excludeSearch"],_28);if(!_28&&config.options.chkAutoSave){saveChanges();}};config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["SettingsPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/#%5B%5BSettingsPlugin%20Documentation%5D%5D]].\sn\sn^^You may copy the documentation tiddler from the website to your TiddlyWiki.\snThen you don't need to access the internet to read the documentation.^^";config.shadowTiddlers["SettingsPlugin SourceCode"]="Rightclick this [[link|http://tiddlywiki.abego-software.de/src/Plugin-Settings-src.js]] and choose 'Save target/link as...' to get the plugin source code from the abego Software website.";config.shadowTiddlers["Show Settings"]="<<showSettings>>";if(config.options[_c]===undefined){config.options[_c]=false;}if(config.options[_d]===undefined){config.options[_d]=false;}config.shadowTiddlers.AdvancedOptions+="\sn''Private Settings: ''<<option "+_c+">> Use private settings. <<option "+_d+">> Make setting private when changed.   [[Show Settings]].\sn^^(Private settings are stored in this ~TiddlyWiki, shared settings are stored as cookies. For more information see the [[Settings documentation|SettingsPlugin Documentation]].)^^";abego.usePrivateSettings=function(){return _f;};abego.setUsePrivateSettings=function(f){if(f!=abego.usePrivateSettings()){_f=f;loadOptionsCookie();}};abego.isUsePrivateSettingsOption=function(_2e){return _2e==_c;};abego.makeSettingPrivateWhenChanged=function(){return config.options[_d];};abego.setMakeSettingPrivateWhenChanged=function(f){config.options[_d]=f;};abego.getSettings=function(){var _30={};_1c(_30);_f=_30[_c]=="true";if(abego.usePrivateSettings()){_19(_30);}return _30;};abego.getSetting=function(_31){var s=abego.getSettings()[_31];return !s?"":s;};abego.saveSetting=function(_33,_34){if(abego.isUsePrivateSettingsOption(_33)){_22(_33,_34);abego.setUsePrivateSettings(_34=="true");loadOptionsCookie();window.alert("You changed the 'Use private settings' option.\snPlease reload your TiddlyWiki to update the settings.\sn");return;}if(abego.usePrivateSettings()&&(abego.isSettingPrivate(_33)||abego.makeSettingPrivateWhenChanged())){_25(_33,_34);}else{_22(_33,_34);}};abego.isSettingPrivate=function(_35){if(abego.isUsePrivateSettingsOption(_35)){return false;}if(!_e){_20();}return !!_e[_35];};abego.isPasswordSetting=function(_36){return (_36.substr(0,3)=="pas")||(_36.substr(0,6)=="chkpas");};abego.makeSettingPrivate=function(_37,_38,_39){if(abego.isPasswordSetting(_37)){_25(_37,null,_39);return;}var _3a=_20();var _3b=_3a[_37]!==undefined;if(_38==_3b){return;}var _3c=_1e();if(_38){_25(_37,_3c[_37],_39);}else{if(_3c[_37]===undefined){_22(_37,_3a[_37]);}_25(_37,null,_39);}};abego.setAllSettingsPrivate=function(_3d,_3e){var _3f=abego.getSettings();for(var s in _3f){abego.makeSettingPrivate(s,_3d,true);}if(config.options.chkAutoSave){saveChanges();}if(_3e){story.refreshTiddler(_3e,1,true);}return false;};})();config.macros.showSettings={label:"showSettings",prompt:"Display the current TiddlyWiki settings"};config.macros.showSettings.handler=function(_41,_42,_43,_44,_45,_46){var _47=function(a){var s=a.substr(0,3);return s=="txt"||s=="chk";};var _4a=function(a,b){var s1=a.toLowerCase();var s2=b.toLowerCase();return (s1<s2)?-1:(s1==s2)?0:1;};var _4f=function(a,b){var _52=_47(a);var _53=_47(b);if(_52){if(!_53){return -1;}else{return _4a(a.substr(3),b.substr(3));}}else{if(_53){return 1;}else{return _4a(a,b);}}};var s="<html><table><tr align=\s"left\s"><th>Private</th><th>Name</th><th>Value</th></tr>";var c=abego.getSettings();var _56=[];for(var i in c){if(!abego.isPasswordSetting(i)){_56.push(i);}}_56.sort(_4f);for(i=0;i<_56.length;i++){var _58=_56[i];var _59=_47(_58)?_58.substr(3)+" ("+_58.substr(0,3)+"...)":_58;var _5a=abego.isUsePrivateSettingsOption(_58)?"":"<input name=\s""+_58+"\s" type=\s"checkbox\s" onclick=\s"abego.onPrivateSettingClick(this)\s""+(abego.isSettingPrivate(_58)?" checked":"")+"/>";s+="<tr><td align=\s"right\s">"+_5a+"</td><td>"+_59+"</td><td>"+c[_58]+"</td></tr>\sn";}s+="</table>";s+="<a class=\s"button\s" title=\s"Make all current settings private\s" href=\s"javascript:;\s" onclick=\s"abego.setAllSettingsPrivate(true,'"+_46.title+"',1);\s">Make all private</a>";s+="<a class=\s"button\s" title=\s"Make all current settings shared\s" href=\s"javascript:;\s" onclick=\s"abego.setAllSettingsPrivate(false,'"+_46.title+"',1);\s">Make all shared</a>";s+="</html>";wikify(s,_41);};abego.onPrivateSettingClick=function(_5b){abego.makeSettingPrivate(_5b.name,_5b.checked);return false;};this.loadOptionsCookie=function(){if(safeMode){return;}var _5c=abego.getSettings();for(var _5d in _5c){var _5e=_5c[_5d];switch(_5d.substr(0,3)){case "txt":config.options[_5d]=unescape(_5e);break;case "chk":config.options[_5d]=_5e=="true";break;}}};this.saveOptionCookie=function(_5f){if(safeMode){return;}var v="";switch(_5f.substr(0,3)){case "txt":v=config.options[_5f].toString();break;case "chk":v=config.options[_5f]?"true":"false";break;}abego.saveSetting(_5f,v);};loadOptionsCookie();}\n// %/\n\n
!Description\nBy default the settings that you can change in the [[options|OptionsPanel]] panel and the [[AdvancedOptions]] are shared by all ~TiddlyWikis of the same site.\n \nThis also means that all your local ~TiddlyWikis share the same settings. This is not always what you want, especially when you are working with multiple local ~TiddlyWikis at once.\n\nThe SettingsPlugin allows you to decide "per setting" if a setting should be shared by all ~TiddlyWikis or if a setting should be "private" to a given ~TiddlyWiki. Alternatively you may also decide that all settings should be private to a given ~TiddlyWiki.\n\n''Using Private Settings''\n\nBy default all settings are "shared", i.e. the settings behave in their standard way. To enable the "private settings" feature check the "Use private settings" checkbox in the AdvancedOptions.\n\nOnce private settings are enabled you have two options:\n* All changes to settings should be "private", i.e. don't affect other ~TiddlyWikis. Therefore check the "Make setting private when changed" checkbox in the AdvancedOptions. \n* Individual settings should be private. You can specify the settings in the [[Show Settings]] tiddler. Here you can also make all settings shared or private, with one click. The [[Show Settings]] tiddler can be accessed through the AdvancedOptions.\n\nYou can decide what settings should be private or shared individually for every ~TiddlyWiki.\n\nYou may temporarily switch off "Use private settings". Then your private settings will not be used. When you switch on again "Use Private Settings", your decision what settings should be private or shared and also the private values will be remembered.\n\n''How Settings are Stored''\n\nAs in the original ~TiddlyWiki code shared settings/options are stored as "cookies" with your browser.\nPrivate settings are stored in a tiddler of the ~TiddlyWiki. You need to ensure that the ~TiddlyWiki can be saved when you want to keep your private settings.\n\n\n!Revision history\n* v1.1.0\n** Support Internet Explorer\n** Don't save password options ("pas..."/"chkpas...") as private settings, and don't display them in the showSettings. Thanks to BidiX for the implementation.\n** Bugfix: Invalid syntax HTML stmt for the "private" settings checkboxes. Thanks to BidiX for the fix.\n* v1.0.2\n** Bugfix: corrected "suspendNotification" bug. Thanks to Jack, BobEverson and MorrisGray for reporting.\n* v1.0.1 \n** Bugfix: Corrected wrong comment in compressed version of plugin.\n** Internal: Simplified "saveTiddler" code. Thanks to Jeremy Ruston for the suggestion.\n* v1.0.0 (2006-04-03)\n** initial version\n\n\n!Code\nThe SettingsPlugin SourceCode contains compressed source code. You will find the full source code [[here|SettingsPlugin SourceCode]].\n
{{{\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.tags+"|\sn"'\n>>\n}}}\n\n//''Explaination:''//\n\nThe interesting part of this task is the creation of the table.\n\nThe idea here is to "write" the same stuff that you would write manually in a tiddler to generate such a table. For every tiddler you would write:\n|{{{|[[}}}//titleOfTiddler//{{{]]|}}}//tagsOfTiddler//{{{|}}}|\n\nInstead of typing the title and looking up the tags you can just ask the [[ForEachTiddlerMacro]] to do the job:\n* instead of //titleOfTiddler// you write {{{tiddler.title}}}\n* instead of //tagsOfTiddler// you write {{{tiddler.tags}}}\n\nYou now need to create a JavaScript expression to build the complete line together:\n* The constant parts ({{{|[[}}}, {{{]]|}}} and {{{|}}}) must be quoted:{{{"|[["}}}, {{{"]]|"}}} and {{{"|"}}}\n* The part are all concatenated to one long string.\n* At the end we need a "newline" character ("\sn") to start the next tiddler in a new line.\n\nThis all ends up in: {{{"|[["+tiddler.title+"]]|"+tiddler.tags+"|\sn"}}}.\n\n//''Result:''//\n<<forEachTiddler \n where \n 'tiddler.title.contains("it")'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.tags+"|\sn"'\n>>\n\nSee also ForEachTiddlerExamples.
The idea is to use the {{{<<tiddler ... >>}}} macro to include the contents. I.e. we would write something like:\n{{{\n<<forEachTiddler ... write ..."<<tiddler ...>>" ...>>\n}}}\nThe problem is that TiddlyWiki takes the first ">>" after a macro as the macro's end. I.e. it processes a macro that looks like this:\n{{{\n<<forEachTiddler ... write ..."<<tiddler ...>>\n}}}\nThis leads to an error.\n\nTo avoid this we escape the {{{>>}}} of the inner macro with the string {{{$))}}}:\n{{{\n<<forEachTiddler\n where\n 'tiddler.title.startsWith("Site")'\n write\n '"----\sn<<tiddler [["+tiddler.title+"]]$))\sn"'\n>>\n}}}\n//(Also adds a separator line before every tiddler)//\n\nThis way the correct end of the macro is detected and we get the following\n\n''//Result://''\n<<forEachTiddler\n where\n 'tiddler.title.startsWith("Site")'\n write\n '"----\sn<<tiddler [["+tiddler.title+"]]$))\sn"'\n>>\n\nSee also [[ForEachTiddlerExamples]].
<<goto>><<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<upload http://dpl.tiddlyspot.com/store.cgi index.html . . dpl>><html><a href='http://dpl.tiddlyspot.com/download' class='button'>download</a></html><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
an over stuffed monkey pirate TiddlyWiki
Guru Notebook
<<slideShow>> - A simple slide show that keeps the TW style \n<<slideShow style:'MySSStyleSheet' clock:'+'>> - A themed slide show with a clock showing the presentation elapsed time\n<<slideShow repeat clock:'-20'>> - A looping slide show with a 20 minutes countdown clock\n<<slideShow slidePause:1000>> - A timed slideshow that runs once\n<<slideShow slidePause:1000 repeat>> - A timed looping slideshow\n-s-\n!The [[SlideShowPlugin]]\nPress F11 to go fullscreen and adjust the font sizes with Ctrl++ Ctrl+- (or Ctrl+mousewheel).\n\nThis plugin was developed by Paulo Soares and Clint Checketts.\n{{Comment{This block is not shown in the slide show.\n@@Don't show me!!!@@}}}\n-s-\n!How slides are separated\nIn a tiddler, you start each slide with the markup {{{-s-}}}\n-s-\nSlides don't have to have titles like this poor one\n-s-\n!A slide with subsections and a long title\nCheck to TOC below to see how this slide title is abbreviated.\n!!Section 1\nThis is a section\n!!!Subsection 1.1\nThis is a subsection\n!!!Subsection 1.2\nThis is another subsection\n!!!!Subsubsection 1.2.1\nThis is a subsubsection\n-s-\n!Using the keyboard\nThe following keys are defined:\n*Left arrow - previous overlay\n*Down arrow - previous slide\n*Right arrow - next overlay\n*Up arrow - next slide\n*Home - first slide\n*End - last slide\n*Escape - exit slide show\n*Spacebar - pause/resume slide show in auto advance mode\n-s-\n!Slide show parameters\n*The slide show can be themed by providing a ~StyleSheet ({{{<<slideShow style:'MyStyleSheet'>>}}})\n*By default, there is a clock at bottom of the browser window that displays the current time. This clock can also show the presentation elapsed time with {{{<<slideShow clock:'+'>>}}} or a countdown clock with {{{<<slideShow clock:'-20'>>}}} (for 20 minutes). In these two cases, if you click on the clock display it will be restarted\n*The slide show can be set to loop ({{{<<slideShow repeat>>}}})\n*You can set it so each slide changes after X milliseconds ({{{<<slideShow slidePause:X>>}}}) (auto advance mode)\n*Use auto start mode to begin the slideshow the moment the tiddler is opened ({{{<<slideShow autostart>>>}}})\n*You can disable overlays with {{{<<slideShow noOverlays>>}}}\n*These parameters can be mixed and matched in any order: {{{<<slideShow slidePause:1000 repeat>>}}} is the same as {{{<<slideShow repeat slidePause:1000>>}}}\n-s-\n!Overlays\nTo see how incremental display works use the left and right mouse buttons.\n{{Overlay1{You can}}} {{Overlay2{present things}}} {{Overlay1{in an arbitrary order!!!}}}\n{{Overlay3{Its a bit harder with lists but it works:}}}\n<html>\n<ol>\n<li class="Overlay4">First item</li>\n<li class="Overlay5">Second item</li>\n<li class="Overlay4">Last item</li>\n</ol>\n</html>\n{{Comment{You can hide comments on a slide that won't display in the slide show}}}
/***\n|''Name:''|SlideShowPlugin|\n|''Description:''|Creates a simple slide show type display|\n|''Version:''|1.5.0|\n|''Date:''|Sep 18, 2006|\n|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|\n|''Author:''|Paulo Soares (psoares (at) math (dot) ist (dot) utl (dot) pt) and [[Clint Checketts|http://www.checkettsweb.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<<tiddler SlideShowPluginDoc>>\n!Code\n***/\n//{{{\nconfig.macros.slideShow = {label: "slide show", maxTOCLength: 30};\nconfig.macros.slideShow.messages = {gotoLabel: "Go to slide:"};\nconfig.views.wikified.slideShow = {text: "slide show", tooltip: "Start slide show"};\nconfig.views.wikified.slideShow.quit = {text: "end", tooltip: "Quit the slide show"};\nconfig.views.wikified.slideShow.firstSlide = {text: "<<", tooltip: "first slide"};\nconfig.views.wikified.slideShow.previousSlide = {text: "<", tooltip: "previous slide"};\nconfig.views.wikified.slideShow.nextSlide = {text: ">", tooltip: "next slide"};\nconfig.views.wikified.slideShow.lastSlide = {text: ">>", tooltip: "last slide"};\nconfig.views.wikified.slideShow.resetClock = {text: " ", tooltip: "reset"};\n\nconfig.formatters.push( {\n name: "SlideSeparator",\n match: "^-s-+$\s\sn?",\n handler: function(w)\n {\n createTiddlyElement(w.output,"hr",null,'slideSeparator');\n }\n}\n)\n\nfunction changeStyleSheet(tiddlerName) {\n if (tiddlerName == null) tiddlerName = "StyleSheet";\n setStylesheet(store.getRecursiveTiddlerText("StyleSheetColors"),"StyleSheetColors");\n setStylesheet(store.getRecursiveTiddlerText("StyleSheetLayout"),"StyleSheetLayout");\n var theCSS = store.getRecursiveTiddlerText(tiddlerName,"");\n setStylesheet(theCSS,"StyleSheet");\n}\n\n//Excellent (and versatile) reparser created by Paul Petterson for parsing the paramString in a macro\nfunction reparse( params ) {\n var re = /([^:\ss]+)(?:\s:((?:\sd+)|(?:["'](?:[^"']+)["']))|\ss|$)/g;\n var ret = new Array() ;\n var m ;\n while( (m = re.exec( params )) != null ) ret[ m[1] ] = m[2]?m[2]:true ;\n return ret ;\n}\n\nfunction getElementsByClass(searchClass,node,tag) {\n var classElements = new Array();\n if ( node == null ) node = document;\n if ( tag == null ) tag = '*';\n var els = node.getElementsByTagName(tag);\n var elsLen = els.length;\n var pattern = new RegExp("(^|\s\ss)"+searchClass+"(\s\ss|$)");\n var j=0;\n for (var i = 0; i < elsLen; i++) {\n if ( pattern.test(els[i].className) ) {\n classElements[j] = els[i];\n j++;\n }\n }\n return classElements;\n}\n\n// 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)\nfunction keys(key) {\n if (document.getElementById('contentWrapper').className == "slideShowMode"){\n if (!key) {\n key = event;\n key.which = key.keyCode;\n }\n switch (key.which) {\n case 32: // spacebar\n if(time>0){\n if(autoAdvance){\n clearInterval(autoAdvance);\n autoAdvance = null;\n } else {\n autoAdvance=setInterval("GoToSlide(1)", time);\n }\n }\n break;\n case 34: // page down\n case 39: // rightkey\n GoToSlide("n");\n break;\n case 40: // downkey\n GoToSlide(-1);\n break;\n case 33: // page up\n case 37: // leftkey\n GoToSlide("p");\n break;\n case 38: // upkey\n GoToSlide(1);\n break;\n case 36: // home\n GoToSlide("f");\n break;\n case 35: // end\n GoToSlide("l");\n break;\n case 27: // escape\n endSlideShow();\n break;\n }\n\n }\n return false;\n}\n\nfunction clicker(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n //Whenever something is clicked that won't advance the slide make sure that the table of contents gets hidden\n if (target.getAttribute('href') != null || isParentOrSelf(target, 'toc') || isParentOrSelf(target,'embed') || isParentOrSelf(target,'object') || isParentOrSelf(target, 'pageFooter') || isParentOrSelf(target, 'navigator')){\n //Don't hide the TOC if the indexNumbers (which trigger the index) is clicked\n if(isParentOrSelf(target,'indexNumbers') || isParentOrSelf(target,'jumpInput')){\n return true;\n }\n showHideTOC('none');\n return true;\n }\n \n //Advance a slide if the TOC is visible otherwise make sure that the TOC gets hidden\n if ((!e.which && e.button == 1) || e.which == 1) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide("n");\n } else {\n showHideTOC('none');\n }\n }\n \n if ((!e.which && e.button == 2) || e.which == 3) {\n if (document.getElementById('toc').style.display != 'block'){\n GoToSlide("p");\n } else {\n showHideTOC('none');\n }\n return false;\n }\n}\n\nfunction isParentOrSelf(element, id) {\n if (element == null || element.nodeName=='BODY') return false;\n else if (element.id == id) return true;\n else return isParentOrSelf(element.parentNode, id);\n}\n\nGoToSlide=function(step) {\n var new_pos;\n var slideHolder = document.getElementById('slideContainer');\n //The parse float ensures that the attribute is returned as a number and not a string.\n var cur_pos = parseFloat(slideHolder.getAttribute('currentslide'));\n var numberSlides = parseFloat(slideHolder.getAttribute('numberSlides'));\n switch (step) {\n case "f":\n new_pos=0;\n break;\n case "l":\n new_pos=numberSlides-1;\n break;\n case "n":\n var numberOverlays = parseFloat(slideHolder.childNodes[cur_pos].getAttribute('numberOverlays'));\n var currentOverlay = parseFloat(slideHolder.getAttribute('currentOverlay'));\n if(numberOverlays==0 || currentOverlay==numberOverlays){\n new_pos=cur_pos+1;\n } else {\n var className="Overlay"+currentOverlay;\n var overlay=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(var i=0; i<overlay.length; i++) {overlay[i].className=className+' previousOverlay';}\n currentOverlay++;\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n className="Overlay"+currentOverlay;\n overlay=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(i=0; i<overlay.length; i++) {overlay[i].className=className+' currentOverlay';}\n return false;\n }\n break;\n case "p":\n var numberOverlays = parseFloat(slideHolder.childNodes[cur_pos].getAttribute('numberOverlays'));\n var currentOverlay = parseFloat(slideHolder.getAttribute('currentOverlay'));\n if(numberOverlays==0 || currentOverlay==0){\n new_pos=cur_pos-1;\n } else {\n var className="Overlay"+currentOverlay;\n var overlays=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(var i=0; i<overlays.length; i++) {overlays[i].className=className+' nextOverlay';}\n currentOverlay--;\n className="Overlay"+currentOverlay;\n overlays=getElementsByClass(className,slideHolder.childNodes[cur_pos]);\n for(i=0; i<overlays.length; i++) {overlays[i].className=className+' currentOverlay';}\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n return false;\n }\n break;\n default:\n new_pos=cur_pos+step;\n }\n\n if(slideShowCircularMode && new_pos == numberSlides) new_pos=0;\n if(slideShowCircularMode && new_pos<0) new_pos=(numberSlides - 1);\n if(step!=0 && new_pos>=0 && new_pos<numberSlides) {\n slideHolder.childNodes[cur_pos].style.display='none';\n slideHolder.childNodes[new_pos].style.display='block';\n slideHolder.setAttribute('currentslide',new_pos);\n var numberOverlays = parseFloat(slideHolder.childNodes[new_pos].getAttribute('numberOverlays'));\n if(step=="p"){\n var currentOverlay=numberOverlays;\n var state=' previousOverlay';\n } else {\n var currentOverlay=0;\n var state=' nextOverlay';\n }\n slideHolder.setAttribute('currentOverlay',currentOverlay);\n if(numberOverlays>0) {\n for(var i=1; i<=numberOverlays; i++){\n var className="Overlay"+i;\n var overlays=getElementsByClass(className,slideHolder.childNodes[new_pos]);\n for(var j=0; j<overlays.length; j++) {overlays[j].className=className+state;}\n }\n if(step=="p"){\n var className="Overlay"+numberOverlays;\n var overlays=getElementsByClass(className,slideHolder.childNodes[new_pos]);\n for(var j=0; j<overlays.length; j++) {overlays[j].className=className+' currentOverlay';}\n }\n }\n new_pos++;\n var indexNumbers = document.getElementById('indexNumbers');\n indexNumbers.firstChild.data = new_pos+'/'+numberSlides;\n if((new_pos==numberSlides) && !slideShowCircularMode && autoAdvance) clearInterval(autoAdvance);\n return true;\n }\n return false;\n}\n\nfunction tocShowSlide(e) {\n if (!e) var e = window.event;\n var target = resolveTarget(e);\n var slide = target.getAttribute('slideNumber');\n var cur_pos = document.getElementById('slideContainer').getAttribute('currentslide');\n var step = slide-cur_pos;\n if(step!=0) GoToSlide(step);\n showHideTOC('none');\n return;\n}\n\n//Toggle the display of the table of contents\nfunction showHideTOC(display){\n var toc = document.getElementById('toc');\n //Reset the input box\n document.getElementById('jumpInput').value = "";\n\n if (display == null || display.length == null){\n if (toc.style.display == 'none' || toc.style.display == ''){\n toc.style.display = 'block';\n document.getElementById('jumpInput').focus();\n } else {\n toc.style.display = 'none';\n }\n } else {\n toc.style.display = display;\n if (display == 'block')\n document.getElementById('jumpInput').focus();\n }\n}\n\nfunction makeSignature(title,params){\n var signature = title+store.getTiddler(title).modified;\n if(params['style']) signature += params['style'];\n if(params['repeat']) signature += "repeat";\n if(params['slidePause'] > 0) signature += params['slidePause'];\n if(params['autostart']) signature += "autostart";\n if(params['clock']) signature += params['clock'];\n if(params['noOverlays']) signature += "noOverlays";\n return signature;\n}\n\nfunction padZero(x){\n return (x>=10 || x<0 ? "" : "0")+x;\n}\n\nsetClock=function(){\n var actualTime = new Date();\n var newTime = actualTime.getTime() - clockStartTime;\n newTime = clockMultiplier*newTime+clockInterval+clockCorrection;\n actualTime.setTime(newTime);\n newTime = padZero(actualTime.getHours()) + ":" + padZero(actualTime.getMinutes())+ ":" + padZero(actualTime.getSeconds());\n var clock = document.getElementById('slideClock');\n clock.firstChild.nodeValue = newTime;\n}\n\nresetClock=function(){\n var time = new Date(0);\n if(clockStartTime>time){\n var startTime = new Date();\n clockStartTime=startTime.getTime();\n }\n}\n\nvar title;\nvar place;\nvar autoAdvance=null;\nvar autoStart=null;\nvar slideClock=null;\nvar noOverlays=false;\nvar time = 0;\nvar slideShowCircularMode;\nvar slideShowStyleSheet;\nvar slideShowParams;\nvar clockMultiplier;\nvar clockInterval;\nvar clockCorrection=0;\nvar clockStartTime;\nvar openTiddlers;\n\nconfig.macros.slideShow.handler = function(aPlace,macroName,params,wikifier,paramString,tiddler){\n if(tiddler instanceof Tiddler){\n var lingo = config.views.wikified.slideShow;\n var autostart = false;\n if (!e) var e = window.event;\n \n place = aPlace;\n title = tiddler.title;\n params = reparse(paramString);\n var onclick = function(){config.macros.slideShow.onClickSlideShow(params);};\n createTiddlyButton(aPlace,lingo.text,lingo.tooltip,onclick);\n \n var slideShowHolder = document.getElementById('slideShowWrapper');\n //If no show exist previously, create it\n if(params['autostart']){\n if(slideShowHolder != null){\n var signature = slideShowHolder.getAttribute('showSignature');\n if(signature.indexOf("autostart")==-1) autostart = true;\n } else {autostart = true;}\n if(autostart){\n slideShowParams = params;\n setTimeout(config.macros.slideShow.onClickSlideShow,100);\n }\n }\n }\n}\n\nvar disableFunction = function(e){return false;}\nvar enableFunction = function(e){}\n\nconfig.macros.slideShow.onClickSlideShow = function(newParams) {\n if(typeof(newParams)=="number") newParams=slideShowParams;\n openTiddlers = new Array;\n var viewer=document.getElementById('tiddlerDisplay');\n for(var i=0; i<viewer.childNodes.length; i++){\n var name = viewer.childNodes[i].getAttribute('tiddler');\n openTiddlers.push(name);\n }\n document.oncontextmenu = disableFunction;\n clockMultiplier = 1;\n clockInterval = 0;\n var startTime = new Date(0);\n slideShowCircularMode = false;\n time = 0;\n slideShowStyleSheet = null;\n if(newParams['style']){\n slideShowStyleSheet = eval(newParams['style']);\n } \n if(newParams['repeat']){\n slideShowCircularMode = true;\n }\n if(newParams['slidePause'] > 0){\n time = newParams['slidePause'];\n }\n if(newParams['clock']){\n clockCorrection=startTime.getTimezoneOffset()*60000;\n startTime = new Date();\n var clockType= eval(newParams['clock']);\n if(clockType != '+') {\n clockMultiplier = -1;\n clockInterval = -clockType*60000;\n }\n }\n clockStartTime=startTime.getTime();\n if(newParams['noOverlays']){\n noOverlays = true;\n }\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className != "slideShowMode"){\n clearMessage();\n //Attach the key and mouse listeners\n document.onkeyup = keys;\n document.onmouseup = clicker;\n \n var slideShowHolder = document.getElementById('slideShowWrapper');\n //If no show exist previously, create it\n if(slideShowHolder == null){\n createSlides(newParams);\n //If there was once waiting in the background and it matches the one we just started, resume it\n } else if (slideShowHolder.getAttribute('showSignature') == makeSignature(title,newParams)){\n \n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n theTiddler.insertBefore(slideShowHolder,viewer);\n theTiddler.removeChild(viewer);\n slideShowHolder.style.display = 'block';\n document.getElementById("pageFooter").className = "pageFooterOff";\n \n //If the show we started it totally new than the resumable one, create the new one and kill the resumable one\n } else {\n slideShowHolder.parentNode.removeChild(slideShowHolder);\n createSlides(newParams);\n }\n slideClock=setInterval("setClock()", 1000); \n if(time>0) autoAdvance=setInterval("GoToSlide(1)", time); \n story.closeAllTiddlers(title);\n toggleSlideStyles();\n } else {\n endSlideShow();\n }\n return ;\n \n}\n\nfunction endSlideShow(){\n //Set aside show so it can be resumed later\n var showHolder = document.getElementById('slideShowWrapper');\n showHolder.style.display = 'none';\n document.getElementById('contentWrapper').parentNode.appendChild(showHolder);\n document.oncontextmenu = enableFunction;\n if(autoAdvance) clearInterval(autoAdvance);\n if(slideClock) clearInterval(slideClock);\n story.refreshTiddler(title,null,true);\n story.closeAllTiddlers();\n toggleSlideStyles();\n story.displayTiddlers(null,openTiddlers,DEFAULT_VIEW_TEMPLATE);\n document.onmouseup = function(){};\n}\n\nfunction isInteger(s){\n var i;\n for (i = 0; i < s.length; i++){\n // Check that current character is number.\n var c = s.charAt(i);\n if (((c < "0") || (c > "9"))) return false;\n }\n // All characters are numbers.\n return true;\n}\n\nfunction jumpInputToSlide(e){\n if (!e) {\n e = window.event;\n e.which = e.keyCode;\n }\n if(e.which==13){\n var jumpInput= document.getElementById("jumpInput").value;\n if(isInteger(jumpInput)){\n var step=jumpInput-document.getElementById('slideContainer').getAttribute('currentslide')-1;\n if (GoToSlide(step)){\n showHideTOC('none'); \n }\n }\n }\n return;\n}\n\n//Used to shorten the TOC fields\nfunction abbreviateLabel(label){\n var maxTOCLength = config.macros.slideShow.maxTOCLength;\n if(label.length>maxTOCLength) {\n var temp = new Array();\n temp = label.split(' ');\n label = temp[0];\n for(var j=1; j<temp.length; j++){\n if((label.length+temp[j].length)<=maxTOCLength){\n label += " " + temp[j];\n } else {\n label += " ...";\n break;\n }\n }\n }\n return label;\n}\n\ncreateSlides = function(newParams){\n var lingo = config.views.wikified.slideShow;\n\n //Remove dblClick on edit function\n var theTiddler = document.getElementById("tiddler"+title);\n theTiddler.ondblclick = function() {};\n\n // Grab the 'viewer' element and give it a signature so the show can be resumed if stopped\n var tiddlerElements = theTiddler.childNodes;\n var viewer;\n for (var i = 0; i < tiddlerElements.length; i++){\n if (tiddlerElements[i].className == "viewer") viewer = tiddlerElements[i];\n }\n viewer.id = 'slideShowWrapper';\n viewer.setAttribute("showSignature",makeSignature(title,newParams));\n\n //Hide the text that comes before the first H1 element (I think I may put this into a cover page type thing)\n while(viewer.childNodes.length > 0 && viewer.firstChild.nodeName.toUpperCase() != "HR" && viewer.firstChild.className!="slideSeparator") {\n viewer.removeChild(viewer.firstChild);\n }\n \n //Cycle through the content and each time you hit an H1 begin a new slide div\n var slideNumber = 0;\n var slideHolder = document.createElement('DIV');\n slideHolder.id = "slideContainer";\n \n while(viewer.childNodes.length > 0){\n //Create a new slide a append it to the slide holder\n if (viewer.firstChild.nodeName.toUpperCase() == "HR" && viewer.firstChild.className=="slideSeparator"){\n slideNumber++;\n var slide = document.createElement('DIV');\n slide.id = "slideNumber"+slideNumber;\n slide.className = "slide";\n if (slideNumber > 1) {\n slideHolder.setAttribute('currentslide',0);\n slide.style.display='none';\n } else {\n slide.style.display='block';\n }\n slideHolder.appendChild(slide); \n viewer.removeChild(viewer.firstChild);\n } else {\n if(viewer.firstChild.nodeName=="SPAN" && viewer.firstChild.className=="" && viewer.firstChild.hasChildNodes()) {\n var anchor=viewer.firstChild.nextSibling;\n for (var ii=0;ii<viewer.firstChild.childNodes.length;ii++) {\n var clone=viewer.firstChild.childNodes[ii].cloneNode(true);\n viewer.insertBefore(clone,anchor);\n }\n viewer.removeChild(viewer.firstChild);\n } else {\n slide.appendChild(viewer.firstChild);\n }\n }\n }\n \n //Stick the slides back into the viewer\n viewer.appendChild(slideHolder);\n slideHolder.setAttribute('numberSlides',slideNumber);\n \n //Create the navigation bar\n var pagefooter = createTiddlyElement(viewer,"DIV","pageFooter","pageFooterOff");\n var navigator = createTiddlyElement(pagefooter,"SPAN","navigator");\n\n //Make it so that when the footer is hovered over the class will change to make it visible\n pagefooter.onmouseover = function () {pagefooter.className = "pageFooterOn"};\n pagefooter.onmouseout = function () {pagefooter.className = "pageFooterOff"};\n\n //Create the control button for the navigation \n var onClickQuit = function(){endSlideShow();};\n createTiddlyButton(navigator,lingo.quit.text,lingo.quit.tooltip,onClickQuit);\n createTiddlyButton(navigator,lingo.firstSlide.text,lingo.firstSlide.tooltip,first_slide);\n createTiddlyButton(navigator,lingo.previousSlide.text,lingo.previousSlide.tooltip,previous_slide);\n createTiddlyButton(navigator,lingo.nextSlide.text,lingo.nextSlide.tooltip,next_slide);\n createTiddlyButton(navigator,lingo.lastSlide.text,lingo.lastSlide.tooltip,last_slide); \n createTiddlyButton(navigator,lingo.resetClock.text,lingo.resetClock.tooltip,resetClock,"button","slideClock"); \n\n var indexNumbers = createTiddlyElement(pagefooter,"SPAN","indexNumbers","indexNumbers","1/"+slideNumber)\n indexNumbers.onclick = showHideTOC;\n var toc = createTiddlyElement(pagefooter,"UL","toc");\n var ovl=1;\n for (var i=0;i<slideHolder.childNodes.length;i++) {\n if(!noOverlays) {\n var ovl=1;\n while(1){\n var className="Overlay"+ovl;\n var overlays=getElementsByClass(className,slideHolder.childNodes[i]);\n if(overlays.length>0){\n for(var j=0; j<overlays.length; j++) {overlays[j].className+=' nextOverlay';}\n ovl++;\n } else {break;}\n }\n }\n slideHolder.childNodes[i].setAttribute("numberOverlays",ovl-1);\n slideHolder.setAttribute("currentOverlay",0);\n\n //Loop through each slide and check the header's content\n var tocLabel = null; \n for (var j=0;j<slideHolder.childNodes[i].childNodes.length;j++) {\n var node = slideHolder.childNodes[i].childNodes[j];\n if(node.nodeName=="H1" || node.nodeName=="H2" || node.nodeName=="H3" || node.nodeName=="H4") {\n var htstring = node.innerHTML;\n var stripped = htstring.replace(/(<([^>]+)>)/ig,"");\n tocLabel = abbreviateLabel(stripped);\n var tocLevel="tocLevel"+node.nodeName.charAt(1);\n var tocItem = createTiddlyElement(toc,"LI",null,tocLevel);\n var tocLink = createTiddlyElement(tocItem,"A",null,"tocItem",tocLabel);\n tocLink.setAttribute("slideNumber",i);\n tocLink.onclick=tocShowSlide;\n }\n }\n }\n \n\n //Input box to jump to s specific slide\n var tocItem = createTiddlyElement(toc,"LI",null,"tocJumpItem",config.macros.slideShow.messages.gotoLabel);\n var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");\n tocJumpInput.type="text";\n tocJumpInput.onkeyup=jumpInputToSlide;\n}\n\nvar next_slide= function(e){GoToSlide(1);}\nvar first_slide= function(e){GoToSlide("f");}\nvar previous_slide= function(e){GoToSlide(-1);}\nvar last_slide= function(e){GoToSlide("l");}\n\nfunction toggleSlideStyles(){\n var contentWrapper = document.getElementById('contentWrapper');\n if (contentWrapper.className == "slideShowMode"){\n contentWrapper.className = "";\n if(slideShowStyleSheet) changeStyleSheet();\n } else{\n contentWrapper.className = "slideShowMode";\n if(slideShowStyleSheet) changeStyleSheet(slideShowStyleSheet);\n }\n}\n\nsetStylesheet("/***\sn!Slide Mode Styles\sn***/\sn/*{{{*/\sn#contentWrapper.slideShowMode #slideContainer{\sn display: block;\sn}\sn\sn#contentWrapper.slideShowMode .Comment{\sn display: none;\sn}\sn\sn#contentWrapper.slideShowMode .nextOverlay{\sn visibility: hidden;\sn}\sn\sn#contentWrapper.slideShowMode .currentOverlay{\sn visibility: visible;\sn}\sn\sn#contentWrapper.slideShowMode .previousOverlay{\sn visibility: visible;\sn}\sn\sn#jump{\sn text-align: right;\sn}\sn\sn.pageFooterOff #navigator{\sn visibility: hidden;\sn}\sn\sn.pageFooterOn #navigator{\sn visibility: visible;\sn}\sn\sn#contentWrapper.slideShowMode #slideClock{\sn cursor: pointer; margin: 0 5px 0 5px; border: 1px solid #db4\sn}\sn\sn#contentWrapper.slideShowMode,\sn #contentWrapper.slideShowMode #displayArea{\sn width: 100%;\sn font-size: 1.5em;\sn margin: 0 !important;\sn padding: 0;\sn}\sn\sn#slideContainer{\sn display: none;\sn}\sn\sn#contentWrapper.slideShowMode #sidebar,\sn#contentWrapper.slideShowMode #mainMenu,\sn#contentWrapper.slideShowMode .header,\sn#contentWrapper.slideShowMode #displayArea .toolbar,\sn#contentWrapper.slideShowMode #displayArea .footer,\sn#contentWrapper.slideShowMode #displayArea .subtitle,\sn#contentWrapper.slideShowMode #displayArea .tagged,\sn#contentWrapper.slideShowMode #displayArea .tagging\sn{\sn display:none !important;\sn}\sn\sn.indexNumbers{\sn cursor: pointer;\sn}\sn\sn#navigator{\sn visibility: hidden;\sn bottom: 0;\sn}\sn\sn#toc{\sn display: none;\sn position: absolute;\sn font-size: .75em;\sn bottom: 2em;\sn right: 0;\sn background: #fff;\sn border: 1px solid #000;\sn text-align: left;\sn}\sn\snul#toc, #toc li{\sn margin: 0;\sn padding: 0;\sn list-style: none;\sn line-height: 1em;\sn}\sn\sn.tocJumpItem{\sn margin-right: 2em;\sn}\sn\sn.tocJumpItem input{\snmargin-right: 1em;\sn border: 0;\sn}\sn\sn#toc a,\sn#toc a.button{\sn display: block;\sn padding: .1em;\sn}\sn\sn#toc .tocLevel1{\snfont-size: .8em;\sn}\sn\sn#toc .tocLevel2{\sn margin-left: 1em;\sn font-size: .75em;\sn}\sn\sn#toc .tocLevel3{\sn margin-left: 2em;\snfont-size: .75em;\sn}\sn\sn#toc .tocLevel4{\sn margin-left: 3em;\snfont-size: .65em;\sn}\sn\sn#toc a{\sn cursor: pointer;\sn}\sn\snh1{\sn min-height: 1em;\sn}\sn\sn.slide h1{\sn min-height: 0;\sn}\sn\sn/* The '>' selector is ignored by IE6 and earlier so the proper rules are given */\sn#pageFooter{\sn position: fixed;\sn bottom: 2px;\sn right: 2px;\sn width: 100%;\sn text-align: right;\sn}\sn\sn/* This is a hack to trick IE6 and earlier to put the navbar on the bottom of the page */\sn* html #pageFooter {\sn position: absolute;\sn width: 100%;\sn text-align: right;\sn right: auto; bottom: auto;\sn left: expression( ( -20 - pageFooter.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );\sn top: expression( ( -10 - pageFooter.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );\sn}\sn\sn\sn\sn/*}}}*/","slideShowStyles");\n//}}}
!Description\nThis plugin turns a TiddlyWiki tiddler into a simple slide show type display. Most features that are usually found in presentation software are available. It should work in a way that does not interfere with TiddlyWiki. When you close the slide show you get back to your good old TW. \n\nThis plugin has been tested in Firefox and Internet Explorer. Let me know if something seems broken.\n\n@@WARNING:@@ this plugin relies on a standard TW layout. Some changes to that layout may lead to improper and unexpected behaviour.\n!Usage\nTo use this plugin you //must// be using TiddlyWiki 2.0. Some optional features (as the incremental display) require version 2.0.8 or higher. To install the plugin copy this tiddler to your TW, label it with the //systemConfig// tag, save the TW and refresh the browser.\n\nTo make a slide show simply drop {{{<<slideShow>>}}} at the beginning of a tiddler and use {{{--s--}}} to start each slide. \n\nIf you move your mouse over the bottom of the browser window you will see a few navigation buttons, a clock and a table of contents that shows up when you click the slide number.\n\nAny block of text marked as {{{{{Comment{For my eyes only!}}}}}} will not be displayed in the slide show.\n\nSee these and other features in this [[SlideShowExample]].\n!Incremental display\nA succession of overlays (or layers) can be defined in each slide by marking blocks of text with {{{{{Overlay1{...some text...}}}}}}, {{{{{Overlay2{...some text...}}}}}}, {{{{{Overlay3{...some text...}}}}}}, ...\n\nTo costumize the way overlays are shown you can redefine the following CSS classes\n*contentWrapper.slideShowMode .previousOverlay \n*contentWrapper.slideShowMode .currentOverlay \n*contentWrapper.slideShowMode .nextOverlay \nin a ~StyleSheet. The default style simply hides the next overlays and shows the current and the previous ones as normal text.\n!Slide show parameters\n*The slide show can be themed by providing a ~StyleSheet ({{{<<slideShow style:'MyStyleSheet'>>}}})\n*By default, there is a clock at bottom of the browser window that displays the current time. This clock can also show the presentation elapsed time with {{{<<slideShow clock:'+'>>}}} or a countdown clock with {{{<<slideShow clock:'-20'>>}}} (for 20 minutes). In these two cases, if you click on the clock display it will be restarted\n*The slide show can be set to loop ({{{<<slideShow repeat>>}}})\n*You can set it so each slide changes after X milliseconds ({{{<<slideShow slidePause:X>>}}}) (auto advance mode)\n*Use auto start mode to begin the slideshow the moment the tiddler is opened ({{{<<slideShow autostart>>>}}})\n*You can disable overlays with {{{<<slideShow noOverlays>>}}}\n*These parameters can be mixed and matched in any order: {{{<<slideShow slidePause:1000 repeat>>}}} is the same as {{{<<slideShow repeat slidePause:1000>>}}}\n!Slide show navigation\nYou can navigate through a slide show using the keyboard or the mouse. To quickly move to titled sections you can use the table of contents. \n!!Mouse navigation\nLeft (right) clicking on a slide jumps to the next (previous) overlay. To move to the beginning of the next or previous slide you must use the navigation bar at the bottom of the browser's window. If there are no overlays defined both operations are equivalent.\n!!Keyboard navigation\nThe following keys are defined:\n*Left arrow - previous overlay\n*Down arrow - previous slide\n*Right arrow - next overlay\n*Up arrow - next slide\n*Home - first slide\n*End - last slide\n*Escape - exit slide show\n*Spacebar - pause/resume slide show in auto advance mode\n!Revision history\n*1.5.0 18/09/2006\n**fixed restoring stylesheet on exit\n**changed (again!) the way how slides are separated (slide shows prepared for previous versions must be fixed)\n*1.4.0 20/04/2006\n**changed the way how slides are separated (slide shows prepared for previous versions must be fixed)\n**now works with content included with the {{{<<tiddler>>}}} macro\n**added incremental display (overlays)\n**improved documentation\n**assorted small fixes\n*1.3.1 10/03/2006\n**removed empty slide titles\n**fixed wrong numberSlides when slides have div's\n**fixed wrong time in Windows\n*1.3.0 26/02/2006\n**restore open tiddlers on exit\n**fixed problem with markup in headers (should work with NestedSlidersPlugin)\n**added slide comments (blocks of text in the tiddler that don't show up in the presentation)\n*1.2.1 28/01/2006\n**pause timed slideshow with spacebar\n**added clock with 3 different modes\n**fixed bugs with style and abbreviation options\n**general cleanup\n*1.2.0 07/01/2006\n**added a resume feature\n**added themes support\n*1.1.5 14/12/2005\n**added mouse support\n**cleaned up navbar generation\n*1.1.0 12/12/2005\n**added support for IE\n**added key listeners\n*1.0.0 11/12/2005\n**initial release\n!Todo\n*Time code is still very hackerish and unreliable.
When using TiddlyWiki 2.0+ you may refer to the date a tiddler was created through the "created" property:\n* [[Sort Tiddlers by 'Create' Date (TiddlyWiki 2.0+)]]\n\nTiddler's prior to TiddlyWiki 2.0 don't include a "Create" date by default. But you may use plugins to add this functionality. Depending on the plugin your ForEachTiddlerMacro call will differ.\n* [[Sort Tiddlers by 'Create' Date (CreationTimePlugin version)]]\n* [[Sort Tiddlers by 'Create' Date (AutoTaggerPlugin version)]]\n
Here are some examples that show the usage of the sortClause in the ForEachTiddlerMacro.\n\n<<forEachTiddler\n where\n 'tiddler.tags.contains("sortClauseExample")'\n>>\nSee also ForEachTiddlerExamples.
I cdnuolt blveiee taht I cluod aulaclty uesdnatnrd waht I was rdanieg.\n\nThe phaonmneal pweor of the hmuan mnid. Aoccdrnig to a rscheearch at\nCmabrigde Uinervtisy, it deosn't mttaer in waht oredr the ltteers in a\nwrod are, the olny iprmoatnt tihng is taht the frist and lsat ltteer be\nin the rghit pclae. The rset can be a taotl mses and you can sitll raed\nit wouthit a porbelm. Tihs is bcuseae the huamn mnid deos not raed\nervey lteter by istlef, but the wrod as a wlohe. Amzanig huh? Yaeh,\nand I awlyas thought slpeling was ipmorantt
/***\n\n''Inspired by [[TiddlyPom|http://www.warwick.ac.uk/~tuspam/tiddlypom.html]]''\n\n|Name|SplashScreenPlugin|\n|Created by|SaqImtiaz|\n|Location|http://lewcid.googlepages.com/lewcid.html#SplashScreenPlugin|\n|Version|0.21 |\n|Requires|~TW2.08+|\n!Description:\nProvides a simple splash screen that is visible while the TW is loading.\n\n!Installation\nCopy the source text of this tiddler to your TW in a new tiddler, tag it with systemConfig and save and reload. The SplashScreen will now be installed and will be visible the next time you reload your TW.\n\n!Customizing\nOnce the SplashScreen has been installed and you have reloaded your TW, the splash screen html will be present in the MarkupPreHead tiddler. You can edit it and customize to your needs.\n\n!History\n* 20-07-06 : version 0.21, modified to hide contentWrapper while SplashScreen is displayed.\n* 26-06-06 : version 0.2, first release\n\n!Code\n***/\n//{{{\nvar old_lewcid_splash_restart=restart;\n\nrestart = function()\n{ if (document.getElementById("SplashScreen"))\n document.getElementById("SplashScreen").style.display = "none";\n if (document.getElementById("contentWrapper"))\n document.getElementById("contentWrapper").style.display = "block";\n \n old_lewcid_splash_restart();\n \n if (splashScreenInstall)\n {if(config.options.chkAutoSave)\n {saveChanges();}\n displayMessage("TW SplashScreen has been installed, please save and refresh your TW.");\n }\n}\n\n\nvar oldText = store.getTiddlerText("MarkupPreHead");\nif (oldText.indexOf("SplashScreen")==-1)\n {var siteTitle = store.getTiddlerText("SiteTitle");\n var splasher='\sn\sn<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>'+siteTitle +'</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>';\n if (! store.tiddlerExists("MarkupPreHead"))\n {var myTiddler = store.createTiddler("MarkupPreHead");}\n else\n {var myTiddler = store.getTiddler("MarkupPreHead");}\n myTiddler.set(myTiddler.title,oldText+splasher,config.options.txtUserName,null,null);\n store.setDirty(true);\n var splashScreenInstall = true;\n}\n//}}}
OSX X11 1.1.2 Update\nThis update addresses several issues in the X11 for Mac OS X package, enabling it to better handle:\n\nGLX stereo visuals\noffscreen rendering to GLX Pbuffers and Pixmaps\nTo tell X11 to take advantage of stereo visuals, enter:\n\n $ defaults write com.apple.x11 enable_stereo -bool true
[[MptwStyleSheet]]\n
[[Plugin: Syntaxify]] syntax-highlights CSS, XML, and Javascript in your tiddlywiki, using the tiddlywiki Wikifier. Take a look at the tiddlers below. Then see [[Plugin: Syntaxify]] for the code to install.\n\n!CSS markup:\n# StyleSheetColors\n# StyleSheetLayout\n# StyleSheetPrint\n# StyleSheetSyntaxify\n{{css{\n#foo .bar { color: red; margin-left: 1em; }\n}}}\n\n!XML markup:\n# EditTemplate\n# PageTemplate\n# ViewTemplate\n{{xml{\n<tag foo="bar" />\n}}}\n\n!Javascript markup:\n# [[Plugin: Syntaxify]]\n{{javascript{\nvar mangle = function(x) { return x.replace("foo","bar"); };\n}}}
The syntax of the configuration file might seem peculiar and complex compared to the traditional syslog.conf syntax, but it offers almost limitless customization options. Make sure to read the syslog-ng.conf man page for information on how to use it.\n\nSince our logging system will gather logs from other hosts, we need to instruct it to listen for network connections. Syslog-ng supports both the TCP and UDP protocols. IANA has assigned the 514/udp port to the syslog service, so we will use that port for maximum compatibility with syslogd and network devices such as routers. If you use syslog-ng on all your hosts, it's better to use the TCP protocol, which is more reliable and firewall-friendly.\n\nAdd the following lines to your /etc/syslog-ng/syslog-ng.conf to the appropriate sections indicated by comments (lines starting with #) to enable listening for network connections on a specific IP address, and to archive logs from remote hosts as /var/log/$HOST/$FACILITY (e.g. /var/log/mailserver/mail):\n{{{\n## add this to the options section\ncreate_dirs(yes);\nlong_hostnames(off);\nkeep_hostname(yes);\n\n# uncomment the following line only on a LAN with working DNS\n#use_dns(yes);\n\n## add this to the source section\nsource s_udp {\n udp ( ip(192.168.1.2) ); # replace with your system's IP address\n};\n\n## add this to the destination section\ndestination df_udp {\n file ("/var/log/$HOST/$FACILITY");\n};\n\n## add this to the log section\nlog {\n source(s_udp);\n destination (df_udp);\n};\n}}}\nOn the remote hosts add the following lines in /etc/syslog-ng/syslog-ng.conf or /etc/syslog.conf, depending on whether they run syslog-ng or syslogd respectively:\n{{{\n## /etc/syslog-ng/syslog-ng.conf\n\n## add this to the destination section\ndestination remote_udp { udp("192.168.1.2"); }; # replace with your log server's IP address\n\n## add this to the log section\nlog { source(src); destination(remote_udp); };\n}}}\n{{{\n## /etc/syslog.conf\n\n# use tabs instead of space\n*.* @192.168.1.2 # replace with your log server's IP address\n}}}\nYou can add additional filters to better suit your needs or even log to a database like PostgreSQL. Note that syslog traffic between hosts is unencrypted; if you want to gather logs from remote hosts over the Internet, create SSH tunnels first, for security.\n\nhttp://www.linux.com/article.pl?sid=06/09/18/1814234
/***\nJavascript implementation of ''T''iny ''E''ncryption ''A''lgorythm\nTaken from [[Movable Type Script|http://www.movable-type.co.uk/scripts/TEAblock.html]]\n***/\n//{{{\n//\n// TEAencrypt: Use Corrected Block TEA to encrypt plaintext using password\n// (note plaintext & password must be strings not string objects)\n//\n// Return encrypted text as string\n//\nfunction TEAencrypt(plaintext, password)\n{\n if (plaintext.length == 0) return(''); // nothing to encrypt\n // 'escape' plaintext so chars outside ISO-8859-1 work in single-byte packing, but \n // keep spaces as spaces (not '%20') so encrypted text doesn't grow too long, and \n // convert result to longs\n var v = strToLongs(escape(plaintext).replace(/%20/g,' '));\n if (v.length == 1) v[1] = 0; // algorithm doesn't work for n<2 so fudge by adding nulls\n var k = strToLongs(password.slice(0,16)); // simply convert first 16 chars of password as key\n var n = v.length;\n\n var z = v[n-1], y = v[0], delta = 0x9E3779B9;\n var mx, e, q = Math.floor(6 + 52/n), sum = 0;\n\n while (q-- > 0) { // 6 + 52/n operations gives between 6 & 32 mixes on each word\n sum += delta;\n e = sum>>>2 & 3;\n for (var p = 0; p < n-1; p++) {\n y = v[p+1];\n mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z)\n z = v[p] += mx;\n }\n y = v[0];\n mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z)\n z = v[n-1] += mx;\n }\n // note use of >>> in place of >> due to lack of 'unsigned' type in JavaScript \n\n return escCtrlCh(longsToStr(v));\n}\n\n//\n// TEAdecrypt: Use Corrected Block TEA to decrypt ciphertext using password\n//\nfunction TEAdecrypt(ciphertext, password)\n{\n if (ciphertext.length == 0) return('');\n var v = strToLongs(unescCtrlCh(ciphertext));\n var k = strToLongs(password.slice(0,16)); \n var n = v.length;\n\n var z = v[n-1], y = v[0], delta = 0x9E3779B9;\n var mx, e, q = Math.floor(6 + 52/n), sum = q*delta;\n\n while (sum != 0) {\n e = sum>>>2 & 3;\n for (var p = n-1; p > 0; p--) {\n z = v[p-1];\n mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z)\n y = v[p] -= mx;\n }\n z = v[n-1];\n mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z)\n y = v[0] -= mx;\n sum -= delta;\n }\n\n var plaintext = longsToStr(v);\n // strip trailing null chars resulting from filling 4-char blocks:\n if (plaintext.search(/\s0/) != -1) plaintext = plaintext.slice(0, plaintext.search(/\s0/));\n\n return unescape(plaintext);\n}\n\n\n// supporting functions\n\nfunction strToLongs(s) { // convert string to array of longs, each containing 4 chars\n // note chars must be within ISO-8859-1 (with Unicode code-point < 256) to fit 4/long\n var l = new Array(Math.ceil(s.length/4))\n for (var i=0; i<l.length; i++) {\n // note little-endian encoding - endianness is irrelevant as long as \n // it is the same in longsToStr() \n l[i] = s.charCodeAt(i*4) + (s.charCodeAt(i*4+1)<<8) + \n (s.charCodeAt(i*4+2)<<16) + (s.charCodeAt(i*4+3)<<24);\n }\n return l; // note running off the end of the string generates nulls since \n} // bitwise operators treat NaN as 0\n\nfunction longsToStr(l) { // convert array of longs back to string\n var a = new Array(l.length);\n for (var i=0; i<l.length; i++) {\n a[i] = String.fromCharCode(l[i] & 0xFF, l[i]>>>8 & 0xFF, \n l[i]>>>16 & 0xFF, l[i]>>>24 & 0xFF);\n }\n return a.join(''); // use Array.join() rather than repeated string appends for efficiency\n}\n\nfunction escCtrlCh(str) { // escape control chars which might cause problems with encrypted texts\n return str.replace(/[\s0\sn\sv\sf\sr\sxa0!]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });\n}\n\nfunction unescCtrlCh(str) { // unescape potentially problematic nulls and control characters\n return str.replace(/!\sd\sd?\sd?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });\n}\n//}}}\n
version.extensions.tagCloud = {major: 0, minor: 1, revision: 0, date: new Date(2005,7,31)}; \n\nconfig.macros.tagCloud = { noTags: "No tag cloud created because there are no tags." }; \n\nconfig.macros.tagCloud.handler = function(place,macroName,params) { \n var tagCloudWrapper = createTiddlyElement(place,"div",null,"tagCloud",null); \n var tags = store.getTags(); \n if(tags.length == 0) \ncreateTiddlyElement(tagCloudWrapper,"span",null,null,this.noTags); \n //Findout the maximum number of tags \n var mostTags = 0; \n for (t=0; t<tags.length; t++) { \n if (tags[t][1] > mostTags) mostTags = tags[t][1]; \n } \n //divide the mostTags into 6 segments for the 6 different tagCloud sizes \n var tagSegment = mostTags / 4; \n for (t=0; t<tags.length; t++) { \n if( tags[t][0].substr(0,6) != "author" && tags[t][0] != "excludeLists" && tags[t][0] != "systemTiddlers")\n{\n var tagCloudElement =createTiddlyElement(tagCloudWrapper,"span",null,null,null); \n tagCloudWrapper.appendChild(document.createTextNode(" ")); \n var theTag = createTiddlyButton(tagCloudElement,tags[t][0],this.tooltip + tags[t][0],onClickTag,"tagCloud"+(Math.round(tags[t][1]/tagSegment)+1)); \n theTag.setAttribute("tag",tags [t][0]); \n theTag.setAttribute("tags",tags [t][0]); \n } \n}\n}; \n\nsetStylesheet(".tagCloud span{height: 1.8em; margin-top: 3px; margin-bottom: 3px; }.tagCloud1{font-size: 1.0em;}.tagCloud2{font-size: 1.2em;}.tagCloud3{font-size: 1.4em;}.tagCloud4{font-size: 1.6em;}.tagCloud5{font-size: 1.8em;font-weight: bold;}","tagCloudsStyles");
/***\n| Name:|TagglyTaggingPlugin|\n| Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|\n| Version:|6.1.5|\n| Date:|05-Oct-2006|\n| Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|\n| Author:|Simon Baird <simon.baird@gmail.com>|\n| CoreVersion:|2.1.x|\n!Notes\nSee http://mptw.tiddlyspot.com/#TagglyTagging\n***/\n//{{{\nconfig.taggly = {\n\n // for translations\n lingo: {\n labels: {\n asc: "\su2191", // down arrow\n desc: "\su2193", // up arrow\n title: "title",\n modified: "modified",\n created: "created",\n show: "+",\n hide: "-",\n normal: "normal",\n group: "group",\n commas: "commas",\n sitemap: "sitemap",\n numCols: "cols\su00b1", // plus minus sign\n label: "Tagged as '%0':"\n },\n\n tooltips: {\n title: "Click to sort by title",\n modified: "Click to sort by modified date",\n created: "Click to sort by created date",\n show: "Click to show tagging list",\n hide: "Click to hide tagging list",\n normal: "Click to show a normal ungrouped list",\n group: "Click to show list grouped by tag",\n sitemap: "Click to show a sitemap style list",\n commas: "Click to show a comma separated list",\n numCols: "Click to change number of columns"\n }\n },\n\n config: {\n showTaggingCounts: true,\n listOpts: {\n // the first one will be the default\n sortBy: ["title","modified","created"],\n sortOrder: ["asc","desc"],\n hideState: ["show","hide"],\n listMode: ["normal","group","sitemap","commas"],\n numCols: ["1","2","3","4","5","6"]\n },\n valuePrefix: "taggly."\n },\n\n getTagglyOpt: function(title,opt) {\n var val = store.getValue(title,this.config.valuePrefix+opt);\n return val ? val : this.config.listOpts[opt][0];\n },\n\n setTagglyOpt: function(title,opt,value) {\n if (!store.tiddlerExists(title))\n // create it silently\n store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),null);\n // if value is default then remove it to save space\n return store.setValue(title,\n this.config.valuePrefix+opt,\n value == this.config.listOpts[opt][0] ? null : value);\n },\n\n getNextValue: function(title,opt) {\n var current = this.getTagglyOpt(title,opt);\n var pos = this.config.listOpts[opt].indexOf(current);\n // a little usability enhancement. actually it doesn't work right for grouped or sitemap\n var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);\n var newPos = (pos + 1) % limit;\n return this.config.listOpts[opt][newPos];\n },\n\n toggleTagglyOpt: function(title,opt) {\n var newVal = this.getNextValue(title,opt);\n this.setTagglyOpt(title,opt,newVal);\n }, \n\n createListControl: function(place,title,type) {\n var lingo = config.taggly.lingo;\n var label;\n var tooltip;\n var onclick;\n\n if ((type == "title" || type == "modified" || type == "created")) {\n // "special" controls. a little tricky. derived from sortOrder and sortBy\n label = lingo.labels[type];\n tooltip = lingo.tooltips[type];\n\n if (this.getTagglyOpt(title,"sortBy") == type) {\n label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];\n onclick = function() {\n config.taggly.toggleTagglyOpt(title,"sortOrder");\n return false;\n }\n }\n else {\n onclick = function() {\n config.taggly.setTagglyOpt(title,"sortBy",type);\n config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);\n return false;\n }\n }\n }\n else {\n // "regular" controls, nice and simple\n label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];\n tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];\n onclick = function() {\n config.taggly.toggleTagglyOpt(title,type);\n return false;\n }\n }\n\n // hide button because commas don't have columns\n if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))\n createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");\n },\n\n makeColumns: function(orig,numCols) {\n var listSize = orig.length;\n var colSize = listSize/numCols;\n var remainder = listSize % numCols;\n\n var upperColsize = colSize;\n var lowerColsize = colSize;\n\n if (colSize != Math.floor(colSize)) {\n // it's not an exact fit so..\n upperColsize = Math.floor(colSize) + 1;\n lowerColsize = Math.floor(colSize);\n }\n\n var output = [];\n var c = 0;\n for (var j=0;j<numCols;j++) {\n var singleCol = [];\n var thisSize = j < remainder ? upperColsize : lowerColsize;\n for (var i=0;i<thisSize;i++) \n singleCol.push(orig[c++]);\n output.push(singleCol);\n }\n\n return output;\n },\n\n drawTable: function(place,columns,theClass) {\n var newTable = createTiddlyElement(place,"table",null,theClass);\n var newTbody = createTiddlyElement(newTable,"tbody");\n var newTr = createTiddlyElement(newTbody,"tr");\n for (var j=0;j<columns.length;j++) {\n var colOutput = "";\n for (var i=0;i<columns[j].length;i++) \n colOutput += columns[j][i];\n var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class\n wikify(colOutput,newTd);\n }\n return newTable;\n },\n\n createTagglyList: function(place,title) {\n switch(this.getTagglyOpt(title,"listMode")) {\n case "group": return this.createTagglyListGrouped(place,title); break;\n case "normal": return this.createTagglyListNormal(place,title,false); break;\n case "commas": return this.createTagglyListNormal(place,title,true); break;\n case "sitemap":return this.createTagglyListSiteMap(place,title); break;\n }\n },\n\n getTaggingCount: function(title) {\n // thanks to Doug Edmunds\n if (this.config.showTaggingCounts) {\n var tagCount = store.getTaggedTiddlers(title).length;\n if (tagCount > 0)\n return " ("+tagCount+")";\n }\n return "";\n },\n\n // this is for normal and commas mode\n createTagglyListNormal: function(place,title,useCommas) {\n\n var list = store.getTaggedTiddlers(title,this.getTagglyOpt(title,"sortBy"));\n\n if (this.getTagglyOpt(title,"sortOrder") == "desc")\n list = list.reverse();\n\n var output = [];\n for (var i=0;i<list.length;i++) {\n var countString = this.getTaggingCount(list[i].title);\n if (useCommas)\n output.push((i > 0 ? ", " : "") + "[[" + list[i].title + "]]" + countString);\n else\n output.push("*[[" + list[i].title + "]]" + countString + "\sn");\n }\n\n return this.drawTable(place,\n this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),\n useCommas ? "commas" : "normal");\n },\n\n // this is for the "grouped" mode\n createTagglyListGrouped: function(place,title) {\n var sortBy = this.getTagglyOpt(title,"sortBy");\n var sortOrder = this.getTagglyOpt(title,"sortOrder");\n\n var list = store.getTaggedTiddlers(title,sortBy);\n\n if (sortOrder == "desc")\n list = list.reverse();\n\n var leftOvers = []\n for (var i=0;i<list.length;i++)\n leftOvers.push(list[i].title);\n\n var allTagsHolder = {};\n for (var i=0;i<list.length;i++) {\n for (var j=0;j<list[i].tags.length;j++) {\n\n if (list[i].tags[j] != title) { // not this tiddler\n\n if (!allTagsHolder[list[i].tags[j]])\n allTagsHolder[list[i].tags[j]] = "";\n\n allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"\n + this.getTaggingCount(list[i].title) + "\sn";\n leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers\n }\n }\n }\n\n var allTags = [];\n for (var t in allTagsHolder)\n allTags.push(t);\n\n var sortHelper = function(a,b) {\n if (a == b) return 0;\n if (a < b) return -1;\n return 1;\n };\n\n allTags.sort(function(a,b) {\n var tidA = store.getTiddler(a);\n var tidB = store.getTiddler(b);\n if (sortBy == "title") return sortHelper(a,b);\n else if (!tidA && !tidB) return 0;\n else if (!tidA) return -1;\n else if (!tidB) return +1;\n else return sortHelper(tidA[sortBy],tidB[sortBy]);\n });\n\n var leftOverOutput = "";\n for (var i=0;i<leftOvers.length;i++)\n leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + "\sn";\n\n var output = [];\n\n if (sortOrder == "desc")\n allTags.reverse();\n else if (leftOverOutput != "")\n // leftovers first...\n output.push(leftOverOutput);\n\n for (var i=0;i<allTags.length;i++)\n output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(leftOvers[i]) + "\sn" + allTagsHolder[allTags[i]]);\n\n if (sortOrder == "desc" && leftOverOutput != "")\n // leftovers last...\n output.push(leftOverOutput);\n\n return this.drawTable(place,\n this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),\n "grouped");\n\n },\n\n // used to build site map\n treeTraverse: function(title,depth,sortBy,sortOrder) {\n\n var list = store.getTaggedTiddlers(title,sortBy);\n if (sortOrder == "desc")\n list.reverse();\n\n var indent = "";\n for (var j=0;j<depth;j++)\n indent += "*"\n\n var childOutput = "";\n for (var i=0;i<list.length;i++)\n if (list[i].title != title)\n childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder);\n\n if (depth == 0)\n return childOutput;\n else\n return indent + "[["+title+"]]" + this.getTaggingCount(title) + "\sn"+childOutput;\n },\n\n // this if for the site map mode\n createTagglyListSiteMap: function(place,title) {\n var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"));\n return this.drawTable(place,\n this.makeColumns(output.split(/(?=^\s*\s[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic\n "sitemap"\n );\n },\n\n macros: {\n tagglyTagging: {\n handler: function (place,macroName,params,wikifier,paramString,tiddler) {\n var refreshContainer = createTiddlyElement(place,"div");\n // do some refresh magic to make it keep the list fresh - thanks Saq\n refreshContainer.setAttribute("refresh","macro");\n refreshContainer.setAttribute("macroName",macroName);\n refreshContainer.setAttribute("title",tiddler.title);\n this.refresh(refreshContainer);\n },\n\n refresh: function(place) {\n var title = place.getAttribute("title");\n removeChildren(place);\n if (store.getTaggedTiddlers(title).length > 0) {\n var lingo = config.taggly.lingo;\n config.taggly.createListControl(place,title,"hideState");\n if (config.taggly.getTagglyOpt(title,"hideState") == "show") {\n createTiddlyElement(place,"span",null,"tagglyLabel",lingo.labels.label.format([title]));\n config.taggly.createListControl(place,title,"title");\n config.taggly.createListControl(place,title,"modified");\n config.taggly.createListControl(place,title,"created");\n config.taggly.createListControl(place,title,"listMode");\n config.taggly.createListControl(place,title,"numCols");\n config.taggly.createTagglyList(place,title);\n }\n }\n }\n }\n },\n\n // todo fix these up a bit\n styles: \n"/*{{{*/\sn"+\n"/* created by TagglyTaggingPlugin */\sn"+\n".tagglyTagging { padding-top:0.5em; }\sn"+\n".tagglyTagging li.listTitle { display:none; }\sn"+\n".tagglyTagging ul {\sn"+\n" margin-top:0px; padding-top:0.5em; padding-left:2em;\sn"+\n" margin-bottom:0px; padding-bottom:0px;\sn"+\n"}\sn"+\n".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }\sn"+\n".tagglyTagging table { margin:0px; padding:0px; }\sn"+\n".tagglyTagging .button { display:none; margin-left:3px; margin-right:3px; }\sn"+\n".tagglyTagging .button, .tagglyTagging .hidebutton {\sn"+\n" color:[[ColorPalette::TertiaryLight]]; font-size:90%;\sn"+\n" border:0px; padding-left:0.3em;padding-right:0.3em;\sn"+\n"}\sn"+\n".tagglyTagging .button:hover, .hidebutton:hover {\sn"+\n" background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];\sn"+\n"}\sn"+\n".selected .tagglyTagging .button {\sn"+\n" display:inline;\sn"+\n"}\sn"+\n".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }\sn"+\n".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }\sn"+\n".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }\sn"+\n".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }\sn"+\n".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}\sn"+\n".tagglyTagging ul ul li {margin-left:0.5em; }\sn"+\n".editLabel { font-size:90%; padding-top:0.5em; }\sn"+\n".tagglyTagging .commas { padding-left:1.8em; }\sn"+\n"/*}}}*/\sn"+\n "",\n\n init: function() {\n merge(config.macros,this.macros);\n config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;\n if (store)\n store.addNotification("TagglyTaggingStyles",refreshStyles);\n else\n config.notifyTiddlers.push({name:"TagglyTaggingStyles", notify: refreshStyles});\n }\n};\n\nconfig.taggly.init();\n\n//}}}\n\n
/***\n|''Name:''|TaskOrganizerPlugin|\n|''Description:''|A simple task manager|\n|''Version:''|1.2.4|\n|''Date:''|Sep 11, 2006|\n|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|\n|''Author:''|Paulo Soares (psoares (at) math (dot) ist (dot) utl (dot) pt)|\n|''License:''|[[BSD open source license]]|\n|''~CoreVersion:''|2.1.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n|''Requires:''|CheckboxPlugin (Eric Shulman), InlineJavascriptPlugin (Eric Shulman) and PartTiddlerPlugin (Udo Borkowski)|\n|''Optional:''|ReminderMacros (Jeremy Sheeley)|\n***/\n/***\n!Description\nThis plugin creates a simple task manager with a variable number of tasks' categories. The management of categories and tasks has been automated. There's also some integration with the ReminderMacros.\nThis is based on previous work by Jim Barr at http://tiddlywikitips.com/TiddlyWikiTasks.html.\n\nThis plugin has been tested in Firefox and Internet Explorer. Let me know if something seems broken.\n!Usage\nInstall this tiddler and drop {{{<<taskOrganizer taskTag>>}}} at the beginning of the tiddler, where taskTag is the tag you want to use with your tasks. You will get an empty task manager. Start adding categories and tasks and it will turn into something like this TaskOrganizerExample. \n!How to update\nBecause this plugin is still in development, some changes make necessary to rebuild the categories' tiddlers (but not the individual tasks!). This can be done manually deleting all your categories (remember to NOT delete the associated tasks) and then recreate them all, one by one. To avoid this procedure I created an option to do this automatically. So, to rebuild all the categories' tiddlers, edit the tiddler with your TaskOrganizer and change {{{<<taskOrganizer taskTag>>}}} to {{{<<taskOrganizer taskTag rebuild>>}}}. Save the tiddler, reopen it and change the text back to {{{<<taskOrganizer taskTag>>}}}. Save again and it should be done. @@Remember to play safely, that is, create a backup before the update.@@\n!Revision history\n1.2.4 - 11/09/2006\n\nA kind contribution by ''Matthew Phillips'' fixed two problems:\n#spaces in the categories' names\n#a task tiddler can have any number of tags\nYou need to rebuild your categories as described above.\n\n1.2.3 - 08/02/2006\n#global vars were eliminated. It's now possible to have several {{{<<taskOrganizer>>}}} entries in the same TW and even in the same tiddler (you need to recreate the categories' tiddlers).\n#the default name for tasks includes the {{{<<taskOrganizer>>}}} tiddler title and category. If you accept this name convention (eg, 'Tasks#Category#task description') this will appear in RSS feeds but will be simplified to 'task description' in the taskOrganizer.\n1.2.2 - 30/01/2006\n#missing requirements handled gracefully (no need to recreate the categories' tiddlers)\n1.2.1 - 28/01/2006\n#ReminderMacros are no longer required and are only used if installed\n#assorted small fixes\n#included an option to rebuild the categories' tiddlers (used for updates)\n1.2.0 - 26/01/2006\n#fixed problem with IE (thanks to Ken Girard) - it looks ugly in IE but seems to work!\n#integration with ReminderMacros\n#dependency on ForEachTiddlerPlugin replaced by InlineJavascriptPlugin for increased flexibility\n#added dependency on the amazing PartTiddlerPlugin (less tiddlers are created this way)\n1.1.1 - 25/01/2006\n#fixed problem with spaces in categories' names (thanks to Ken Girard)\n1.1.0 - 24/01/2006 \n#removed dependency on NewerTiddler plugin\n#added the possibility to delete categories of tasks\n1.0.0 - 21/01/2006\n#initial release\n!Todo\n!Code\n***/\n//{{{\nconfig.macros.button = {};\n\nconfig.macros.button.handler=function(place,macroName,params,wikifier,paramString,tiddler) {\n if(params.length<3) return;\n var myFunction = eval(params[2]);\n place.appendChild(createTiddlyButton(place,params[0],params[1],myFunction));\n}\n\nconfig.macros.taskOrganizer = {};\n\nconfig.macros.taskOrganizer.options = {\n pendingTask: "Pending",\n completedTask: "Completed",\n newTask: {label: "New task", tooltip: "Add a new task"},\n addTaskCategory: {label: "New category", tooltip: "Add a new task category"},\n deleteTaskCategory: {label: "Delete category", tooltip: "Delete this task category"},\n deleteCategoryConfirmation: "Are you sure you want to delete this category?",\n deleteTasksConfirmation: "Are you sure you want to delete all tasks associated to the category?",\n newTaskCategoryPrompt: "Enter the new task category name:"\n}\n\nconfig.macros.taskOrganizer.addCategory = function() {\n var cm = config.macros.taskOrganizer;\n if(typeof arguments[0] != 'string'){\n var newTask = prompt(cm.options.newTaskCategoryPrompt,"");\n var rebuild = false;\n var taskTag = this.parentNode.getAttribute("tag");\n var title = this.parentNode.getAttribute("tiddlerTitle");\n } else {\n var newTask = arguments[0];\n var holder= document.getElementById("tiddler"+arguments[1]);\n var taskTag = holder.getAttribute("tag");\n var title = arguments[1];\n var rebuild = true;\n }\n if(!newTask) return;\n\n var tabTiddler = new Tiddler();\n tabTiddler.title = title+ ":" + newTask;\n tabTiddler.tags[0] = taskTag;\n tabTiddler.tags[1] = "excludeLists";\n tabTiddler.modifier = config.options.txtUserName;\n var titleTask = newTask.replace(/ /g,"=");\n\n tabTiddler.text = "<<tabs \s"txt" + title + ":" + titleTask + "\s"\sn" + cm.options.pendingTask + " " + cm.options.pendingTask + " \s"" + title + ":" + newTask + "/Pending" + "\s"\sn";\n tabTiddler.text += cm.options.completedTask + " " + cm.options.completedTask + " \s"" + title + ":" + newTask + "/Completed" + "\s"\sn>>\sn";\n tabTiddler.text += "<<button '" + cm.options.newTask.label + "' '" + cm.options.newTask.tooltip + "' 'config.macros.taskOrganizer.newTask'>>";\n tabTiddler.text += " <<button '" + cm.options.deleteTaskCategory.label + "' '" + cm.options.deleteTaskCategory.tooltip + "' 'config.macros.taskOrganizer.deleteCategory'>>\sn";\n\n tabTiddler.text += "<part Pending hidden>";\n tabTiddler.text += "<script>\sn var list = \s"\s";\sn";\n tabTiddler.text += "var tiddlers = store.getTaggedTiddlers(\s"" + taskTag + "." + newTask + "\s", \s"created\s");\sn";\n if(config.macros.reminders) tabTiddler.text += "var regexp = new RegExp(\s"<<re\s"+\s"minder .+>>\s", \s"g\s");\sn"\n tabTiddler.text += "for(var i=0; i<tiddlers.length; i++){\snif(!tiddlers[i].tags.contains (\s"completed\s")){\snvar newEntry=tiddlers[i].title.split(\s"#\s");\snlist+=\s"[X(\s"+tiddlers[i].title+\s":completed)] [[\s"+newEntry[newEntry.length-1]+\s"|\s"+tiddlers[i].title+\s"]]\s\sn\s";\sn";\n if(config.macros.reminders){\n tabTiddler.text += "var reminder = tiddlers[i].text.match(regexp);\sn";\n tabTiddler.text += "if(reminder){\sn for(var j=0; j<reminder.length; j++){\sn list += \s"*\s" + reminder[j] + \s"\s\sn\s";}}";\n }\n tabTiddler.text+= "}}\sn return list;\sn";\n tabTiddler.text += "</script>";\n tabTiddler.text += "</part>\sn";\n\n tabTiddler.text += "<part Completed hidden>";\n tabTiddler.text += "<script>\sn var list = \s"\s";\sn";\n tabTiddler.text += "var tiddlers = store.getTaggedTiddlers(\s"" + taskTag + "." + newTask + "\s", \s"created\s");\sn";\n tabTiddler.text += "for(var i=0; i<tiddlers.length; i++){if(tiddlers[i].tags.contains (\s"completed\s")){\sn var newEntry=tiddlers[i].title.split(\s"#\s");\snlist+=\s"[X(\s"+tiddlers[i].title+\s":completed)] [[\s"+newEntry[newEntry.length-1]+\s"|\s"+tiddlers[i].title+\s"]]\s\sn\s";}}\sn";\n tabTiddler.text+= "return list;\sn";\n tabTiddler.text += "</script>";\n tabTiddler.text += "</part>";\n\n store.addTiddler(tabTiddler);\n if(!rebuild) story.refreshTiddler(title,DEFAULT_VIEW_TEMPLATE,true);\n}\n\nconfig.macros.taskOrganizer.deleteCategory=function(){\n if(typeof arguments[0] != 'string'){\n var category = this.parentNode.firstChild.className.split(":")[1];\n category = category.replace(/=/g," ");\n var rebuild = false;\n var taskTag = this.parentNode.parentNode.parentNode.getAttribute("tag");\n var title = this.parentNode.parentNode.parentNode.getAttribute("tiddlerTitle");\n } else {\n var category = arguments[0].split(":")[1];\n var rebuild = true;\n var holder= document.getElementById("tiddler"+arguments[1]);\n var taskTag = holder.getAttribute("tag");\n var title = arguments[1];\n }\n\n var cm = config.macros.taskOrganizer;\n var conf = true;\n if(!rebuild) conf = confirm(cm.options.deleteCategoryConfirmation); \n if(conf){\n store.removeTiddler(title+ ":" + category);\n if(!rebuild){\n story.refreshTiddler(title,DEFAULT_VIEW_TEMPLATE,true);\n var tiddlers = store.getTaggedTiddlers(taskTag + "." + category);\n if(tiddlers.length>0){\n conf = confirm(cm.options.deleteTasksConfirmation); \n if(conf){\n for(var i=0; i<tiddlers.length; i++) store.removeTiddler(tiddlers[i].title);\n }\n }\n }\n }\n}\n\nconfig.macros.taskOrganizer.newTask=function(){\n var category = this.parentNode.firstChild.className.split(":")[1];\n category = category.replace(/=/g," ");\n var cm = config.macros.taskOrganizer;\n var taskTag = this.parentNode.parentNode.parentNode.getAttribute("tag");\n var title = this.parentNode.parentNode.parentNode.getAttribute("tiddlerTitle");\n var tiddlerName = title + "#" + category + "#";\n var newTiddler = new Tiddler();\n newTiddler.title = tiddlerName;\n newTiddler.tags[0] = taskTag + "." + category;\n newTiddler.tags[1] = "excludeLists";\n newTiddler.modifier = config.options.txtUserName;\n if(config.macros.reminders){\n newTiddler.text = "<<newReminder>>";\n } else {newTiddler.text = "";}\n store.addTiddler(newTiddler);\n story.displayTiddler(null,tiddlerName,DEFAULT_EDIT_TEMPLATE);\n story.focusTiddler(tiddlerName,"title");\n}\n\nconfig.macros.taskOrganizer.handler=function(place,macroName,params,wikifier,paramString,tiddler) {\n if(!(version.extensions.CheckboxPlugin && version.extensions.inlineJavascript && version.extensions.PartTiddlerPlugin)){\n var text = "Some required macros are missing!\snPlease check the requirements of this macro [[here|TaskOrganizerPlugin]].";\n } else {\n if(!params) return;\n var taskTag=params[0];\n var rebuild = false;\n if(params[1]=='rebuild') rebuild = true;\n var cm = config.macros.taskOrganizer;\n var tiddlerTitle;\n var tiddlers = store.getTaggedTiddlers(taskTag,"modified");\n var title = tiddler.title;\n var holder= document.getElementById("tiddler"+title);\n holder.setAttribute("tag",taskTag);\n place.setAttribute("tiddlerTitle",title);\n place.setAttribute("tag",taskTag);\n var text = "<<tabs 'txt" + title + "'\sn";\n if(rebuild){\n for(var i=0; i<tiddlers.length; i++) cm.deleteCategory(tiddlers[i].title.split(":")[1], title);\n for(var i=0; i<tiddlers.length; i++) cm.addCategory(tiddlers[i].title.split(":")[1], title);\n }\n for(var i=0; i<tiddlers.length; i++){\n tiddlerTitle = tiddlers[i].title.substring(title.length+1);\n text += "\s"" + tiddlerTitle + "\s" \s"" + tiddlerTitle + "\s" [[" + tiddlers[i].title + "\s]]\sn";\n }\n text += ">>\sn";\n text += "<<button '" + cm.options.addTaskCategory.label + "' '" + cm.options.addTaskCategory.tooltip + "' 'config.macros.taskOrganizer.addCategory'>>";\n }\n wikify(text,place);\n}\n//}}}
/***\n|''Name:''|TiddlerWithParamsPlugin|\n|''Version:''|1.0.1 (2006-03-22)|\n|''Source:''|http://tiddlywiki.abego-software.de/#TiddlerWithParamsPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n!Description\n\nThe TiddlerWithParamsPlugin extends the build-in {{{<<tiddler...>>}}} macro. It replaces placeholders ($1, $2, ...) in the given tiddler by values passed with the macro. Then it inserts the (replaced) text, just like the original {{{<<tiddler...>>}}} macro.\n\n''Syntax:'' \n|>|{{{<<}}}''tiddler '' //tiddlerName// [//className//] [''asText''] [''with:'' //arguments// ] [''prefix:'' //prefixString//] {{{>>}}}|\n|//tiddlerName//|The name of the tiddler to be included. The tiddler may contain placeholders ($1, $2, ... $9) that will be replaced with the values passed with the macro|\n|//className//|The (CSS) class to be used around the embedded tiddler|\n|''asText''|When defined the (replaced) content of the tiddler is inserted as pure text, i.e. it is not "wikified".|\n|//arguments//|up to 9 arguments may be passed to the macro, used as the values for the placeholders $1, $2, ... $9 in the referenced template|\n|//prefixString//|By default the placeholders $1, $2, $3,..., $9 are used. But you may change the "prefix" before the placeholder number ("$") to some other text through the "prefix:" option. This may be necessary when you are using the $n in the tiddler you are referencing (e.g. when you are using regular expressions).|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. ~~|\n\n!Example\n\nThe following ''//ProjectTemplate//'' tiddler defines an "Overview" page for a project, that gives access to various "sub-tiddlers" used in the project, that follow a static naming schema (e.g. all Notes for any project are stored in a tiddler called "//projectName// Notes"). $1 holds the name of the Project (e.g. "ForEachTiddler"), $2 holds the type of the published component (e.g. "Plugin", "Macro", "Function").\n{{{\n![[$1Project]] Overview\n* [[$1$2]]\n* [[ToDo|$1 ToDos]]\n* [[Notes|$1 Notes]]\n* [[Examples|$1Examples]]\n* [[Tests|$1 Tests]]\n* [[Open Bugs/CRs|$1 Open Bugs and ChangeRequests]]\n}}}\n\nThis template is now used in the ''//ForEachTiddlerProject//'' tiddler:\n{{{\n<<tiddler ProjectTemplate with: ForEachTiddler Plugin>>\n}}}\n\nThis results in the following tiddler text for the ''//ForEachTiddlerProject//'' tiddler:\n{{{\n![[ForEachTiddlerProject]] Overview\n* [[ForEachTiddlerPlugin]]\n* [[ToDo|ForEachTiddler ToDos]]\n* [[Notes|ForEachTiddler Notes]]\n* [[Examples|ForEachTiddlerExamples]]\n* [[Tests|ForEachTiddler Tests]]\n* [[Open Bugs/CRs|ForEachTiddler Open Bugs and ChangeRequests]]\n}}}\n\n!Revision history\n* v1.0.0 (2006-01-20)\n** initial version\n* v1.0.1 (2006-03-22)\n** Added 'asText' option\n** Support Safari (Thanks to Elise Springer for reporting the problem)\n!Code\n***/\n//{{{\n//============================================================================\n// TiddlerWithParamsPlugin\n//============================================================================\n\n// Ensure that the Plugin is only installed once.\n//\nif (!version.extensions.TiddlerWithParamsPlugin) {\n\nversion.extensions.TiddlerWithParamsPlugin = {\n major: 1, minor: 0, revision: 1, \n date: new Date(2006,3,22), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#TiddlerWithParamsPlugin"\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nvar indexInArray = function(array, item) {\n for (var i = 0; i < array.length; i++) {\n if (array[i] == item) {\n return i;\n }\n }\n return -1;\n}\n\nvar myEscapeRegExp = function(s)\n{\n // The original escapeRegExp function does not work with Safari (2.0.3) \n // since the $& is not implemented.\nvar t = s.replace(/\s\s/g, "\s\s\s\s");\n t = t.replace(/\s^/g, "\s\s^");\n t = t.replace(/\s$/g, "\s\s$");\n t = t.replace(/\s*/g, "\s\s*");\n t = t.replace(/\s+/g, "\s\s+");\n t = t.replace(/\s?/g, "\s\s?");\n t = t.replace(/\s(/g, "\s\s(");\n t = t.replace(/\s)/g, "\s\s)");\n t = t.replace(/\s=/g, "\s\s=");\n t = t.replace(/\s!/g, "\s\s!");\n t = t.replace(/\s|/g, "\s\s|");\n t = t.replace(/\s,/g, "\s\s,");\n t = t.replace(/\s{/g, "\s\s{");\n t = t.replace(/\s}/g, "\s\s}");\n t = t.replace(/\s[/g, "\s\s[");\n t = t.replace(/\s]/g, "\s\s]");\n t = t.replace(/\s./g, "\s\s.");\n\n return t;\n}\n\n// ---------------------------------------------------------------------------\n// The (hijacked) tiddler Macro Handler \n// ---------------------------------------------------------------------------\n\nconfig.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n \n var className = null;\n var argsStart = -1;\n var doWikify = true;\n\n var iParams = 1;\n if (params[iParams] != "asText" && params[iParams] != "with:") {\n className = params[iParams++];\n }\n if (params[iParams] == "asText") {\n iParams++;\n doWikify = false;\n }\n if (params[iParams] == "with:") {\n iParams++;\n argsStart = iParams;\n }\n \n var wrapper = createTiddlyElement(place,"span",null,className ? className : null,null);\n var text = store.getTiddlerText(params[0]);\n if(text) {\n // Check for recursion\n var tiddlerName = params[0];\n var stack = config.macros.tiddler.tiddlerStack;\n if (stack.find(tiddlerName) !== null) return;\n\n if (argsStart >= 0) {\n // The params between the "with:" and the "prefix:" (or the end) are the arguments,\n // The param behind the "prefix:" is the prefix before the placeholder numbers.\n var argsEnd = params.length;\n var prefix = "$";\n var prefixIndex = indexInArray(params, "prefix:");\n if (prefixIndex >= argsStart) {\n argsEnd = prefixIndex;\n if (prefixIndex < (params.length-1)) {\n prefix = params[prefixIndex+1];\n }\n }\n // to avoid any "special RE chars" problems with the prefix string escape all chars.\n prefix = myEscapeRegExp(prefix);\n \n var args = params.slice(argsStart, argsEnd);\n var n = Math.min(args.length, 9);\n for (var i = 0; i < n; i++) {\n var value = args[i];\n \n var placeholderRE = new RegExp(prefix+(i+1),"mg");\n text = text.replace(placeholderRE, value);\n }\n }\n stack.push(tiddlerName);\n try {\n if (doWikify) {\n wikify(text,wrapper,null,store.getTiddler(params[0]));\n } else {\n wrapper.appendChild(document.createTextNode(text));\n }\n } finally { \n stack.pop();\n }\n }\n}\nconfig.macros.tiddler.tiddlerStack = [];\n\n// End of "install only once"\n}\n\n//============================================================================\n// End of TiddlerWithParamsPlugin\n//============================================================================\n//}}}\n/***\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n
http://del.icio.us/TiddlyWikiPlugin
The TiddlySaver Java applet allows TiddlyWiki from a """file://""" URL to save changes Safari, Opera and other browsers.\n\nIt is a small file named "TiddlySaver.jar" that must be placed in the same directory as your TiddlyWiki file. Before you can use it, you need to give it the necessary privileges by editting your .java.policy file.\n\nFor Windows, the file will be at C:\sDocuments and Settings\syour-user-name\s.java.policy. Add the following lines (substituting the directory of your TiddlyWiki file as appropriate):\n{{{\ngrant codeBase "file:${user.home}/My Documents/tiddlywiki-folder/*" {\n permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder${/}*", "read,write";\n};\n}}}\nOn Mac OS X, the file is found at /Users/your-user-name/.java.policy:\n{{{\ngrant codeBase "file:${user.home}/Documents/tiddlywiki-folder/*" {\n permission java.io.FilePermission "${user.home}${/}Documents${/}tiddlywiki-folder${/}*", "read,write";\n};\n}}}\nIt can be tricky creating files whose name starts with a period, so you can use this pre-built .java.policy file. The same file is suitable for Macs too, just edit it and delete the "My " bit, leaving just "Documents". Make sure you save it in the right place for each operating system!\n\nNote that there is currently a bug that prevents TiddlySaver from working if you have specified a backup directory in AdvancedOptions.
<<backupEntry 'Sun Jan 28 22:38:47 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070129.0338470634.html file:>>\n<<backupEntry 'Sun Jan 28 22:38:44 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070129.0338440652.html file:>>\n<<backupEntry 'Fri Jan 12 10:35:26 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1535260098.html file:>>\n<<backupEntry 'Fri Jan 12 10:35:21 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1535210727.html file:>>\n<<backupEntry 'Fri Jan 12 10:30:03 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1530030490.html file:>>\n<<backupEntry 'Fri Jan 12 10:28:14 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1528140891.html file:>>\n<<backupEntry 'Fri Jan 12 10:23:48 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1523480790.html file:>>\n<<backupEntry 'Fri Jan 12 10:15:04 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1515040521.html file:>>\n<<backupEntry 'Fri Jan 12 10:15:00 2007' /Users/Shared/TiddlyWiki/Backup/dpl.20070112.1515000252.html file:>>\n<<backupEntry 'Mon Dec 4 14:20:49 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061204.1920490552.html file:>>\n<<backupEntry 'Fri Dec 1 10:52:34 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061201.1552340818.html file:>>\n<<backupEntry 'Tue Nov 21 18:05:13 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061121.2305130227.html file:>>\n<<backupEntry 'Tue Nov 21 17:10:08 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061121.2210080262.html file:>>\n<<backupEntry 'Tue Nov 21 17:10:03 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061121.2210030110.html file:>>\n<<backupEntry 'Mon Nov 13 16:05:19 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2105190709.html file:>>\n<<backupEntry 'Mon Nov 13 16:05:03 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2105030794.html file:>>\n<<backupEntry 'Mon Nov 13 15:58:40 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2058400726.html file:>>\n<<backupEntry 'Mon Nov 13 15:47:40 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2047400401.html file:>>\n<<backupEntry 'Mon Nov 13 15:45:50 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2045500333.html file:>>\n<<backupEntry 'Mon Nov 13 15:38:53 2006' /Users/Shared/TiddlyWiki/Backup/dpl.20061113.2038530433.html file:>>\n<<backupEntry 'Wed Oct 18 09:29:27 2006' /Users/Shared/TiddlyWiki/dpl.20061018.1329270507.html file:>>\n<<backupEntry 'Fri Oct 13 18:42:02 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2242020848.html file:>>\n<<backupEntry 'Fri Oct 13 18:41:07 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2241070398.html file:>>\n<<backupEntry 'Fri Oct 13 18:40:11 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2240110701.html file:>>\n<<backupEntry 'Fri Oct 13 18:34:45 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2234450083.html file:>>\n<<backupEntry 'Fri Oct 13 18:32:56 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2232560019.html file:>>\n<<backupEntry 'Fri Oct 13 17:45:16 2006' /Users/Shared/TiddlyWiki/dpl.20061013.2145160319.html file:>>\n<<backupEntry 'Fri Oct 13 17:26:41 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.2126410869.html file:>>\n<<backupEntry 'Fri Oct 13 14:14:14 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1814140982.html file:>>\n<<backupEntry 'Fri Oct 13 13:54:17 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1754170923.html file:>>\n<<backupEntry 'Fri Oct 13 13:51:53 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1751530996.html file:>>\n<<backupEntry 'Fri Oct 13 13:50:29 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1750290340.html file:>>\n<<backupEntry 'Fri Oct 13 13:42:13 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1742130145.html file:>>\n<<backupEntry 'Fri Oct 13 13:40:36 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1740360182.html file:>>\n<<backupEntry 'Fri Oct 13 13:39:05 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1739050888.html file:>>\n<<backupEntry 'Fri Oct 13 13:36:50 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1736500155.html file:>>\n<<backupEntry 'Fri Oct 13 13:36:04 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1736040036.html file:>>\n<<backupEntry 'Fri Oct 13 13:26:18 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1726180722.html file:>>\n<<backupEntry 'Fri Oct 13 13:23:36 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1723360290.html file:>>\n<<backupEntry 'Fri Oct 13 12:45:14 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1645140197.html file:>>\n<<backupEntry 'Fri Oct 13 12:44:40 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1644400836.html file:>>\n<<backupEntry 'Fri Oct 13 12:43:59 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1643590462.html file:>>\n<<backupEntry 'Fri Oct 13 12:43:38 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1643380217.html file:>>\n<<backupEntry 'Fri Oct 13 12:43:21 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1643210365.html file:>>\n<<backupEntry 'Fri Oct 13 12:40:30 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1640300812.html file:>>\n<<backupEntry 'Fri Oct 13 12:39:07 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1639070870.html file:>>\n<<backupEntry 'Fri Oct 13 12:38:56 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1638560461.html file:>>\n<<backupEntry 'Fri Oct 13 12:35:26 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1635260651.html file:>>\n<<backupEntry 'Fri Oct 13 12:34:00 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1634000150.html file:>>\n<<backupEntry 'Fri Oct 13 12:32:02 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1632020816.html file:>>\n<<backupEntry 'Fri Oct 13 12:31:09 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1631090014.html file:>>\n<<backupEntry 'Fri Oct 13 12:26:58 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1626580952.html file:>>\n<<backupEntry 'Fri Oct 13 12:24:39 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1624390419.html file:>>\n<<backupEntry 'Fri Oct 13 12:23:51 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1623510774.html file:>>\n<<backupEntry 'Fri Oct 13 12:22:23 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1622230614.html file:>>\n<<backupEntry 'Fri Oct 13 12:18:49 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061013.1618490201.html file:>>\n<<backupEntry 'Thu Oct 12 13:16:37 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061012.1716370334.html file:>>\n<<backupEntry 'Thu Oct 12 13:16:33 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061012.1716330192.html file:>>\n<<backupEntry 'Thu Oct 12 13:14:28 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061012.1714280122.html file:>>\n<<backupEntry 'Thu Oct 12 12:47:24 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061012.1647240027.html file:>>\n<<backupEntry 'Thu Oct 12 12:46:10 2006' /Users/Shared/TiddlyWiki/MyDirtyLittleMonkeyPirate.20061012.1646100044.html file:>>\n<<backupEntry 'mercredi 21 juin 2006 20:15:44' E:\sprojets\ssite\stwkd\ssauvegarde\stwkd.20060621.1815440921.html file:>>\n<<deleteTMTiddler>>
/***\n<<tiddler TimeMachinePluginDocumentation>>\n!Code\n***/\n//{{{\nversion.extensions.timeMachine = { major: 1, minor: 2, revision: 1, date: new Date(2006,12,4),\n source: "http://yann.perrin.googlepages.com/twkd.html#TimeMachinePlugin"\n};\n\nconfig.macros.backupEntry = {};\nconfig.macros.backupEntry.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nwikify("<<timeMachine '" + params[0] + "' " + params[1] + ">>[[" + params[0] + "|" + params[2] + "//" + params[1] + "]]<<timeMachineDeleteEntry '" + params[0] + "' " + params[1] + " " + params[2] + ">>",place);\n}\n\nconfig.macros.timeMachine = {};\nconfig.macros.timeMachine.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nvar loadTooltip = "restore this backup";\nvar loadAction = function(){wikify ('<<importTiddlers "all" ' + params[1] + ' ask>>')};\nif (!readOnly && store.tiddlerExists('ImportTiddlersPlugin')){createTiddlyButton(place,'>>',loadTooltip,loadAction,'loadBackupButton');};\n};\n\nconfig.macros.timeMachineDeleteEntry = {};\nconfig.macros.timeMachineDeleteEntry.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nvar deleteEntryTooltip = "delete this entry";\nvar deleteEntryAction = function(){\n var tiddler = getTimeMachineTiddler();\n var entryText = "<<backupEntry '" + params[0] + "' " + params[1] + " " + params[2] + ">>\sn";\n tiddler.text = tiddler.text.replace(entryText,"");\n tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers['TimeMachine'] = tiddler;\n else\n store.addTiddler(tiddler);\n if (version.major < 2)\n story.refreshTiddler("TimeMachine",1,true);\n store.notifyAll();\n};\ncreateTiddlyButton(place,'x',deleteEntryTooltip,deleteEntryAction,'deleteEntryButton');\n}\n\nconfig.macros.deleteTMTiddler = {};\nconfig.macros.deleteTMTiddler.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\nvar deleteTiddlerText = "Clear History";\nvar deleteTiddlerTooltip = "clear the history of your backups";\nvar deleteTiddlerAction = function() {\n story.closeTiddler(tiddler.title);\n store.deleteTiddler(tiddler.title);\n getTimeMachineTiddler();\n story.refreshTiddler("TimeMachine",1,true);\n store.notifyAll();\n};\ncreateTiddlyButton(place,deleteTiddlerText,deleteTiddlerTooltip,deleteTiddlerAction);\n}\n\n\nfunction getTimeMachineTiddler() {\n var tiddler;\n if (version.major < 2)\n tiddler = store.tiddlers['TimeMachine'];\n else\n tiddler = store.getTiddler("TimeMachine");\n if (!tiddler) \n {\n tiddler = new Tiddler();\n tiddler.title = "TimeMachine";\n tiddler.text = "<<deleteTMTiddler>>";\n tiddler.tags = ["excludeLists","excludeSearch","TimeMachinePlugin"];\n if (version.major < 2)\n store.tiddlers['TimeMachine'] = tiddler;\n else\n store.addTiddler(tiddler);\n }\n return tiddler;\n}\n\nfunction timeMachine(backupPath) \n{\n var tiddler = getTimeMachineTiddler();\n var newLink ="<<backupEntry '" + new Date().toLocaleString() + "' " + backupPath + " " + location.protocol + ">>";\n tiddler.text = newLink + "\sn" + tiddler.text;\n tiddler.modifier = config.options.txtUserName;\n tiddler.modified = new Date();\n if (version.major < 2)\n store.tiddlers['TimeMachine'] = tiddler;\n else\n store.addTiddler(tiddler);\n if (version.major < 2)\n store.notifyAll();\n}\n\n//hijacking getBackupPath to write additionnal lines to TimeMachine Tiddler before saving\ntimeMachineGetBackupPath=getBackupPath;\ngetBackupPath = function(localPath)\n{\nvar backupPath = timeMachineGetBackupPath(localPath);\ntimeMachine(backupPath);\nreturn backupPath;\n}\n\nconfig.shadowTiddlers.TimeMachinePluginDocumentation = "Documentation for this plugin is available [[here|" + version.extensions.timeMachine.source +"Documentation]]";\n//}}}
|Name|TimeMachinePlugin|\n|Author|YannPerrin|\n|Location|http://yann.perrin.googlepages.com/twkd.html#TimeMachinePlugin|\n|Version|1.2.1|\n|Requires|~TW2.x|\n\n!Description\nThis plugin add a backup history to your TiddlyWiki, and let you restore your changes if ImportTiddlersPlugin is intalled.\n\n!Installation\n*import (or copy/paste in edit mode) the following tiddlers into your document:<<br>>TimeMachinePlugin (tagged with systemConfig)\n*add a reference to the TimeMachine tiddler somewhere (in sidebar for example).\n*tag the tiddlers you want to be able to restore with importReplace and importPublic\n*if you want to have offline access to this plugin documentation, import (or copy/paste in edit mode) the following tiddlers into your document:<<br>>TimeMachinePluginDocumentation\n\n!Usage\n''Once properly installed'' (see above) TimeMachinePlugin will start recording your backups in the TimeMachine tiddler.\n*Clicking on a backup date will show you the backup file.\n*If ImportTiddlersPlugin is present, clicking on the '>>' before a backup date will trigger an import of its ''properly tagged'' tiddlers (tiddlers tagged with importReplace and importPublic)<<br>>you will be asked for each of these wether you want to import it or not.\n*Clicking on the 'x' button on the right will delete the associated history entry\n*Clicking on the 'Clear History' button will delete the entire history content.\n!Revision History\n2006.12.04-1.2.1\n>removed installation in shadow SideBarOptions to increase compatibility with other plugins.\n2006.16.03-1.2.0\n>changed backup links to display local date and time instead of ~GMT\n>reworked code to produce an easier to read TimeMachine/history tiddler source.\n>''this will make your old history entries undeletable with their associated delete button'' however you can still clear your history.\n2006.10.03-1.1.0\n>Added css classes loadBackupButton and entryDeleteButton to allow styling of the corresponding buttons.\n>Added preview link to backup file.\n>Removed ImportTiddlersPlugin dependency, with optionnal increase of functionnality if it's present.\n>Separated code and documentation.\n2006.10.03-1.0\n>Initial release\n\n!Credits\n*[[Eric Shulman]] for his very usefull ImportTiddlersPlugin\n
/***\n| Name:|ToggleTagMacro|\n| Description:|Makes a checkbox which toggles a tag in a tiddler|\n| Version:|6.1.6|\n| Date:|06-Oct-2006|\n| Source:|http://tiddlyspot.com/mptw/#ToggleTagMacro|\n| Author:|SimonBaird|\n| License:|[[BSD open source license]]|\n| CoreVersion:|2.1|\n!Usage\n{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}\n* TagName - the tag to be toggled, default value "checked"\n* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler\n* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'\n(If a parameter is '.' then the default will be used)\n\nExamples:\n\n|Code|Description|Example|h\n|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|\n|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|\n|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|\n|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|\n|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|\n(Note if TiddlerName doesn't exist it will be silently created)\n\n!Known issues\n* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing. Should it stick the tag in the edit box?\n\n***/\n//{{{\n\nmerge(config.macros,{\n\n toggleTag: {\n\n doRefreshAll: true,\n createIfRequired: true,\n shortLabel: "[[%0]]",\n longLabel: "[[%0]] [[%1]]",\n\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n var tag = (params[0] && params[0] != '.') ? params[0] : "checked";\n var title = (params[1] && params[1] != '.') ? params[1] : tiddler.title;\n var defaultLabel = (title == tiddler.title ? this.shortLabel : this.longLabel);\n var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;\n var theTiddler = title == tiddler.title ? tiddler : store.getTiddler(title);\n var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {\n if (!theTiddler) {\n if (config.macros.toggleTag.createIfRequired)\n store.saveTiddler(title,title,"",config.options.txtUserName,new Date(),null);\n else\n return false;\n }\n //store.suspendNotifications(); \n store.setTiddlerTag(title,this.checked,tag);\n //refreshDisplay(); \n //store.resumeNotifications();\n return true;\n });\n }\n }\n});\n\n//}}}\n\n
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |\n| 13/10/2006 17:5:25 | YourName | [[/|http://dpl.tiddlyspot.com/]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 13/10/2006 17:12:18 | DanLawson | [[/|http://dpl.tiddlyspot.com/]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 13/10/2006 17:14:39 | DanLawson | [[/|http://dpl.tiddlyspot.com/]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 13/10/2006 17:45:16 | DirtyD | [[dpl.html|file:///Users/Shared/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 13/10/2006 18:42:2 | DirtyD | [[dpl.html|file:///Users/Shared/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 21/11/2006 17:10:7 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 1/12/2006 10:52:34 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 4/12/2006 14:20:48 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 12/1/2007 10:15:4 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 12/1/2007 10:28:14 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . | Ok |\n| 12/1/2007 10:35:25 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.tiddlyspot.com/store.cgi]] | . | index.html | . |\n| 28/1/2007 22:38:47 | DirtyD | [[dpl.html|file:///Users/Shared/TiddlyWiki/dpl.html]] | [[store.cgi|http://dpl.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
*Provider with the best voice quality - http://www.teliax.com/
[[Uncommon Uses for VLC|http://wiki.videolan.org/index.php/Uncommon_uses]]\n!Extended syntax .m3u file syntax example of transcode with stream rebroadcast for iTunes consumption for playback on airTunes\n{{{\n#EXTM3U\n#EXTINF:0,live stream (transcoded)\n#EXTVLCOPT:sout=#transcode{acodec=mpga,ab=192}:standard{access=http}\n#EXTVLCOPT:ttl=1\nmms://213.75.12.55/kpnmms_bnr\n}}}\n!Transcode any source to iPod compatible format\n{{{#!/bin/bash}}}\n{{{vlc -vvv "$1.mpg"\n --sout "#transcode{vcodec=mp4v,vb=1024,scale=1,\n acodec=mp4a,ab=128,channels=2}:standard{access=file,\n url=$1.mp4}"\n --aspect-ratio "4:3" --sout-transcode-width 360\n --sout-transcode-height 240 --sout-transcode-fps 30}}}\n!Stream input via external RTSP server with transcode\n{{{vlc -vvv --extraintf="dummy" --ttl=255 "test.mpg" --loop --aspect-ratio="1.22222" --sout="#transcode:rtp" --sout-transcode-width=176 --sout-transcode-height=144 --sout-transcode-vcodec="mp4v" --sout-transcode-vb="76" --sout-transcode-fps="15" --sout-transcode-acodec="mp4a" --sout-ffmpeg-keyint="10" --sout-transcode-ab="16" --sout-transcode-samplerate="11025" --sout-transcode-channels="1" --sout-rtp-dst="127.0.0.1" --sout-rtp-ttl="255" --sout-rtp-port-video="20000" --sout-rtp-port-audio="20002" --sout-rtp-sdp="file://C:/Program Files/Darwin Streaming Server/Movies/vlc1.sdp"}}}\n!Stream input via internal RTSP server with transcode\n{{{vlc -vvv --extraintf="dummy" --ttl=255 "test.mpg" --loop --aspect-ratio="1.22222" --sout="#transcode:rtp" --sout-transcode-width=176 --sout-transcode-height=144 --sout-transcode-vcodec="mp4v" --sout-transcode-vb="76" --sout-transcode-fps="15" --sout-transcode-acodec="mp4a" --sout-ffmpeg-keyint="10" --sout-transcode-ab="16" --sout-transcode-samplerate="11025" --sout-transcode-channels="1" --sout-rtp-dst="127.0.0.1" --sout-rtp-ttl="255" --sout-rtp-port-video="20000" --sout-rtp-port-audio="20002" --sout-rtp-sdp="rtsp://127.0.0.1/vlc1.sdp"}}}
[[MptwViewTemplate]]\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?// @@ 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://dpl.tiddlyspot.com/controlpanel]] (your control panel username is //dpl//).\n<<tiddler tiddlyspotControls>>\n@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ 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// @@ 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!// @@ 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 :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions.
Here are some examples that show the usage of the whereClause in the ForEachTiddlerMacro.\n\n<<forEachTiddler\n where\n 'tiddler.tags.contains("whereClauseExample")'\n>>\n\nSee also ForEachTiddlerExamples.
[[Wikka - Wiki engine|http://sourceforge.net/projects/wikka]]\nLesserWiki\n[[SpeedyWiki|http://speedywiki.sourceforge.net/]]\n[[Wiki on a Stick|WikiOnAStick]]\n
Wiki on a Stick [[Hompage|http://stickwiki.sourceforge.net/]]\n\nMy [[Wiki on a stick|file:///Users/Shared/MyWikiSticky.html]]
[[Win Libre|http://www.winlibre.org]]\n[[HowTO record via 1394/Firewire to WindowsXP now with MCE support|http://www.avsforum.com/avs-vb/showthread.php?threadid=403695]]\n[[Useful Free Windows Programs Under 2MB|http://revision3.com/forum/showthread.php?t=234]]\n
''//The {{{write}}} action//''\n\n''Syntax'' \n|[''write'' //stringExpression// [''toFile'' //filepath// [''withLineSeparator'' //stringExpression// ] ] ]|\n\nThe {{{write}}} action of the ForEachTiddlerMacro has a parameter that is a (quoted) JavaScript String expression. <<tiddler [[JavaScript in actionParameters]]>>\n\nThe expression is evaluated for every selected tiddler and the results are concatenated to a text (the "result text"). \n\nWhen a "toFile" is specified the result text is written to the given file. In that case one may also specify a "line separator" (through the {{{withLineSeparator}}} option) that is used instead of every "\sn" that appears in the result text.\n\nWhen no "toFile" is specified the result text is inserted in the tiddler at the location of the ForEachTiddlerMacro (similar to the {{{<<tiddler ...>>}}} macro. So if you write expressions resulting in "{{{| ... | ... |}}}" you will see a table, when you write "{{{[img[...]]}}} you see the image etc. .\n\nAlso see [[WriteActionExamples]], e.g. for how to create tables or "embed" the content of a list of tiddlers in another tiddler using the {{{write}}} action.\n
Here are some examples that show the usage of the write action in the ForEachTiddlerMacro.\n\n<<forEachTiddler\n where\n 'tiddler.tags.contains("writeActionExample")'\n>>\nSee also ForEachTiddlerExamples.
/***\n|''Name:''|XHTML10Plugin|\n|''Version:''|1.0.0 (2006-08-01)|\n|''Type:''|plugin|\n|''Source:''|http://tiddlywiki.abego-software.de/#XHTML10Plugin|\n|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|\n|''Documentation:''|[[XHTML10Plugin Documentation]]|\n|''~SourceCode:''|[[XHTML10Plugin SourceCode]]|\n|''Licence:''|[[BSD open source license (abego Software)]]|\n|''~CoreVersion:''|2.1.0|\n|''Browser:''|Firefox 1.5.0.2 or better; Internet Explorer 6.0|\n\nThis plugin makes the ~TiddlyWiki store its tiddlers in an XHTML 1.0 compliant format.\n\nOnce the plugin is installed the existing tiddlers of that TiddlyWiki are automatically converted to the new format on the first save. After that all changes are also written in the XHTML format.\n\n***/\n//{{{\n// Ensure the Plugin is only installed once.\n//\nif (!version.extensions.XHTML10Plugin) {\n\nif (version.major < 2 || (version.major == 2 && version.minor < 1)) {\n (function() {\n var s = "Use TiddlyWiki 2.1 or better to run the XHTML10Plugin.";\n alert(s);\n throw s;\n })();\n}\n\nversion.extensions.XHTML10Plugin = {\n major: 1, minor: 0, revision: 0,\n date: new Date(2006, 7, 1),\n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#XHTML10Plugin",\n documentation: "[[XHTML10Plugin Documentation]]",\n author: "Udo Borkowski (ub [at] abego-software [dot] de)",\n licence: "[[BSD open source license (abego Software)]]",\n coreVersion: "2.1.0",\n browser: "Firefox 1.5.0.2 or better; Internet Explorer 6.0"\n};\n\n// Ensure the global abego namespace is set up.\nif (!window.abego) window.abego = {};\n\n\n//}}}\n/***\n!Start of main code\n***/\n//{{{\n//--------------------------------\n// XHTML10Saver (inherits from SaverBase)\n\nabego.XHTML10Saver = function() {};\n\nabego.XHTML10Saver.prototype = new SaverBase();\n\nabego.XHTML10Saver.prototype.externalizeTiddler = function(store, tiddler) {\n try {\n var s = '';\n store.forEachField(tiddler, \n function(tiddler, fieldName, value) {\n // don't store stuff from the temp namespace\n if (!fieldName.match(/^temp\s./)) {\n if (value)\n value = value.htmlEncode();\n s += ['<pre title="',fieldName,'">',value,'</pre>'].join("");\n }\n });\n return ['<div title="',tiddler.title.htmlEncode(),'">',s,'</div>'].join("");\n\n } catch (e) {\n showException(e, config.messages.tiddlerSaveError.format([tiddler.title]));\n return '';\n }\n};\n\nabego.XHTML10Saver.prototype.externalize = function(store) {\n return ["<div class='twXHTML10'>\sn",SaverBase.prototype.externalize.apply(this, arguments),"\sn</div>"].join("");\n};\n\n\n//--------------------------------\n// Overwrite TiddlyWiki.prototype.getSaver to use the XHTML10 format on save\n\nTiddlyWiki.prototype.getSaver = function() {\n if (!this.saver) \n this.saver = new abego.XHTML10Saver();\n return this.saver;\n};\n\n//======================================\n// Install the Loader into the HTML page\n\n(function() {\n // The loader code will be inserted into the PostHead markup block,\n // so it can be executed before tiddlers are loaded. We cannot just put this\n // code into a normal plugin since this "load" code is required to load\n // tiddlers. I.e. this code must be executed before any tiddlers/plugins\n // can be loaded.\n\n var getXHTML10LoaderBlock = function() {\n // The loader code in a big JavaScript string.\n // You may get a non-stringified version of the XHTML10Loader source code at\n // http://tiddlywiki.abego-software.de/src/XHTML10Loader.js\n\n XHTML10LoaderCode = \n "if (!window.abego) window.abego = {};\snif (!abego.XHTML10Loader) {\sn\st//-"+\n "-------------------------------\sn\st// abego.XHTML10Loader (inherits from"+\n " LoaderBase)\sn\st\sn\stabego.XHTML10Loader = function() {};\sn\stabego.XHTML10Loa"+\n "der.prototype = new LoaderBase();\sn\st\sn\stabego.XHTML10Loader.prototype.lin"+\n "go = {\sn\st\stunnamedValue: \s"Unnamed value\s",\sn\st\stredefining: \s"Redefining valu"+\n "e of %0\s",\sn\st\stnoXHTML10Format: \s"Storage not in XHTML 1.0 format\s"\sn\st}\sn\st\sn\sta"+\n "bego.XHTML10Loader.prototype.getTitle = function(store, e) {\sn\st\stvar tit"+\n "le = null;\sn\st\stif(e.getAttribute)\sn\st\st\sttitle = e.getAttribute('title');\sn\st\st"+\n "if(!title && e.id) {\st\sn\st\st\stvar lenPrefix = store.idPrefix.length;\sn\st\st\stif "+\n "(e.id.substr(0,lenPrefix) == store.idPrefix)\sn\st\st\st\sttitle = e.id.substr(l"+\n "enPrefix);\sn\st\st}\sn\st\streturn title;\sn\st};\sn\st\sn\stabego.XHTML10Loader.prototype.in"+\n "ternalizeTiddler = function(store, tiddler, title, data) {\sn\st\stvar field"+\n "s = {};\sn\st\stvar elems = data.childNodes;\sn\st\stfor(var i = 0; i < elems.leng"+\n "th; i++) {\sn\st\st\stvar e = elems[i];\sn\st\st\stvar name = e.getAttribute('title');"+\n "\sn\st\st\stif (!name) \sn\st\st\st\stthrow this.lingo.unnamedValue;\sn\st\st\stif (fields[name]"+\n " !== undefined) \sn\st\st\st\stthrow this.lingo.redefining.format([name]);\sn\st\st\stfi"+\n "elds[name] = getNodeText(e.firstChild); \sn\st\st}\sn\st\sn\st\st// Extract (and remov"+\n "e) the standard fields from the extended fields\sn\st\stvar text = fields.te"+\n "xt;\sn\st\stvar modifier = fields.modifier;\sn\st\stvar modified = Date.convertFro"+\n "mYYYYMMDDHHMM(fields.modified);\sn\st\stvar c = fields.created;\sn\st\stvar create"+\n "d = c ? Date.convertFromYYYYMMDDHHMM(c) : modified;\sn\st\stvar tags = field"+\n "s.tags;\sn\st\stdelete fields.modifier;\sn\st\stdelete fields.modified;\sn\st\stdelete f"+\n "ields.created;\sn\st\stdelete fields.tags;\sn\st\stdelete fields.text;\sn\st\stdelete fi"+\n "elds.title;\sn\st\sn\st\sttiddler.assign(title,text,modifier,modified,tags,creat"+\n "ed,fields);\sn\st\st\sn\st\streturn tiddler;\sn\st};\sn\st\sn\stvar findRootNode = function(no"+\n "des) {\sn\st\stif (nodes) {\sn\st\st\st// skip leading text nodes\sn\st\st\stfor (var i = 0;"+\n " i < nodes.length; i++)\sn\st\st\st\stif (nodes[i].nodeType != 3)\sn\st\st\st\st\stbreak;\sn\st\st"+\n "\st\st\st\sn\st\st\stif (i < nodes.length && nodes[i].className == 'twXHTML10')\sn\st\st\st\st"+\n "return nodes[i];\sn\st\st}\sn\st};\sn\st\sn\stabego.XHTML10Loader.prototype.loadTiddlers"+\n " = function(store,nodes) {\sn\st\st// in the twXHMTL10 format all tiddler el"+\n "ements are contained in one enclosing DIV\sn\st\st// that contains the forma"+\n "t information\sn\st\stvar root = findRootNode(nodes)\sn\st\stif (!root) \sn\st\st\stthrow "+\n "this.lingo.noXHTML10Format;\sn\st\streturn LoaderBase.prototype.loadTiddlers"+\n ".apply(this, [store, root.childNodes]);\sn\st};\sn\st\sn\st\sn\st//-------------------"+\n "-------------\sn\st// Hijack the loadFromDiv\sn\st(function() {\sn\st\stvar origTidd"+\n "lyWikiLoadFromDiv = TiddlyWiki.prototype.loadFromDiv;\sn\st\stTiddlyWiki.pro"+\n "totype.loadFromDiv = function(srcID,idPrefix) {\sn\st\st\st// use the XHTML 1."+\n "0 loader when the storearea is in 'twXHTML10' format,\sn\st\st\st// otherwise "+\n "use the default loader\sn\st\st\stvar e = document.getElementById(srcID);\sn\st\st\sti"+\n "f (e && findRootNode(e.childNodes))\sn\st\st\st\stthis.loader = new abego.XHTML1"+\n "0Loader();\sn\st\st\streturn origTiddlyWikiLoadFromDiv.apply(this, arguments);"+\n "\sn\st\st};\sn\st})();\sn}\sn\sn";\n return '<'+'script type="text/javascript">\sn//<![CDATA[\sn'+XHTML10LoaderCode+'\sn//]]>\sn</script'+'>\sn';\n };\n\n var insertLoaderBlock = function() {\n if (!store)\n throw "XHTML10LoaderInstaller must run as a plugin";\n \n var START = "<!--XHMTL10Loader-START-->";\n var END = "<!--XHMTL10Loader-END-->";\n \n var postHeadText = store.getTiddlerText("MarkupPostHead");\n if (postHeadText.getChunk(START, END)) \n return; // already installed\n\n postHeadText += "\sn"+START+getXHTML10LoaderBlock()+END+"\sn";\n var tiddler = store.getTiddler("MarkupPostHead");\n var tags = tiddler ? tiddler.tags : [];\n store.saveTiddler("MarkupPostHead","MarkupPostHead",postHeadText,config.options.txtUserName,new Date(),tags);\n alert("XHTML10Loader installed.\snPlease save and reload your TiddlyWiki to complete the installation. After that your TiddlyWiki will be stored in an XHTML 1.0 compliant format.");\n };\n \n insertLoaderBlock(); \n})();\n\n//}}}\n\n/***\n!End of main code\n***/\n\n \n//{{{\n} // of single install\n//}}}\n\n//{{{\n// Used Globals (for JSLint) ==============\n// ... JavaScript Core\n/*global */\n// ... TiddlyWiki Core\n/*global */\n//}}}\n\n\n\n
[[Xen|http://www.cl.cam.ac.uk/research/srg/netos/xen/]]\n\nHow to fix the nosegneg xen-frriendly warning.\n\nCheck your profile \n{{{\nls -l /etc/make.profile\nlrwxrwxrwx 1 root root 48 2006-09-04 15:00 /etc/make.profile -> ../usr/portage/profiles/default-linux/x86/2006.1\n}}}\nThis profile will ensure you're using a recent version of glibc with nptl. You can use any 2006.1 profile (including desktop or server sub profiles).\n\nThe quickest way to update the /usr/portage/profiles directories so that you can update the link above is to download the latest portage snapshot from your nearest mirror. Information on the latest profiles can be found here: http://www.gentoo.org/doc/en/gentoo-upgrading.xml \n\nSome software, in particular the glibc TLS library, is implemented in a way that will conflict with how Xen uses segment registers to circumvent a limitation of 32-bit x86 hardware platforms, causing poor performance whilst carrying out certain operations under Xen. This will result in a ~50% performance penalty running multi-threaded applications. To fix this, you must compile your system with the '-mno-tls-direct-seg-refs' flag. \n\nEdit your /etc/make.conf and add '-mno-tls-direct-seg-refs' to your CFLAGS. This is similar to the Xen instructions to "mv /usr/lib/tls /usr/lib/tls.disabled", but instead removes the trapped (slow) opcodes for every binary, not just glibc.\n\nIf using the -Os flag (with any <gcc-4), change it to -O2, as the compiler is known to produce broken code otherwise. \n\nNote: The '-mno-tls-direct-seg-refs' Flag does not make sense on any 64bit system. For such systems you can skip the recompilation of the whole world and just recompile glibc\n{{{\necho 'sys-libs/glibc nptlonly' >> /etc/portage/package.use\n}}}\nRebuild every package with your new CFLAGS\n{{{\nemerge --emptytree --deep --ask --verbose world\n}}}\n\nNote: You will also need to fix the CFLAGS for each domain U you install! In practice, however, you will do this only once and save the result as your 'skeleton base' for all your domain Us \n\nNote: If you have problems compiling xen (kernel.c fails to compile), try removing 387 support from your make.conf i.e remove 387 from the -mfpmath=sse,387 flag \n\nNote: If GCC does not know the 'no-tls-direct-seg-refs' flag (cc1: error: invalid option `no-tls-direct-seg-refs'), you will need to upgrade to a newer version (3.4 works) as described here: http://www.gentoo.org/doc/en/gcc-upgrading.xml \n\nIf this shows up in your log, even though you've faithfully added the 'no-tls-direct-seg-refs' flag, it means that you have glibc less than 2.4 on your system, so you need to enable it using package.keywords
[[Xen|Xen]]\n[[HOWTO Xen and Gentoo|http://gentoo-wiki.com/HOWTO_Xen_and_Gentoo]]\n
/***\n|''Name:''|YourSearchPlugin|\n|''Version:''|2.0.2 (2006-02-13)|\n|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n<<tiddler [[YourSearch Introduction]]>>\nFor more information see [[Help|YourSearch Help]].\n\n!Compatibility\nThis plugin requires TiddlyWiki 2.0. \nUse http://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1 for older TiddlyWiki versions.\n\n!Revision history\n* v2.0.2 (2006-02-13)\n** Bugfix for Firefox 1.5.0.1 related to the "Show prefix" checkbox. Thanks to Ted Pavlic for reporting and to BramChen for fixing. \n** Internal\n*** Make "JSLint" conform\n* v2.0.1 (2006-02-05)\n** Support "Exact Word Match" (use '=' to prefix word)\n** Support default filter settings (when no filter flags are given in search term)\n** Rework on the "less than 3 chars search text" feature (thanks to EricShulman)\n** Better support SinglePageMode when doing "Open all tiddlers" (thanks to EricShulman)\n** Support Firefox 1.5.0.1\n** Bug: Fixed a hilite bug in "classic search mode" (thanks to EricShulman)\n* v2.0.0 (2006-01-16)\n** Add User Interface\n* v1.0.1 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.0 (2005-12-28)\n** initial version\n!Code\nThe code is compressed. \n\nYou can retrieve a readable source code version from http://tiddlywiki.abego-software.de/#YourSearchPlugin-src.\n/%\n***/\nif(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:0,revision:2,date:new Date(2006,2,13),type:"plugin",source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin"};var alertAndThrow=function(_1){alert(_1);throw _1;};if(!window.abego){window.abego={};}if(abego.YourSearch){alertAndThrow("abego.YourSearch already defined");}abego.YourSearch={};if(version.major<2){alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.0 or newer.\sn\snGet YourSearch 1.0.1 to use YourSearch with older versions of TiddlyWiki.\sn\snhttp://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1");}var STQ=function(_2,_3,_4,_5){this.queryText=_2;this.caseSensitive=_3;if(_5){this.regExp=new RegExp(_2,_3?"mg":"img");return;}this.terms=[];var re=/\ss*(\s-)?([#%!=]*)(?:(?:("(?:(?:\s\s")|[^"])*")|(\sS+)))(?:\ss+((?:[aA][nN][dD])|(?:[oO][rR]))(?!\sS))?/mg;var _7=re.exec(_2);while(_7!=null&&_7.length==6){var _8="-"==_7[1];var _9=_7[2];var _a=_9.indexOf("!")>=0;var _b=_9.indexOf("%")>=0;var _c=_9.indexOf("#")>=0;var _d=_9.indexOf("=")>=0;if(!_a&&!_b&&!_c){_a=config.options.chkSearchInTitle;_b=config.options.chkSearchInText;_c=config.options.chkSearchInTags;if(!_a&&!_b&&!_c){_a=_b=_c=true;}}if(_4){_b=false;_c=false;}var _e;if(_7[3]){try{_e=eval(_7[3]);}catch(ex){}}else{_e=_7[4];}if(!_e){throw "Invalid search expression: %0".format([_2]);}var _f=_7[5]&&_7[5].charAt(0).toLowerCase()=="o";this.terms.push(new STQ.Term(_e,_a,_b,_c,_8,_f,_3,_d));_7=re.exec(_2);}};var me=STQ.prototype;me.getMatchingTiddlers=function(_10){var _11=[];for(var i in _10){var t=_10[i];if((t instanceof Tiddler)&&this.matchesTiddler(t)){_11.push(t);}}return _11;};me.matchesTiddler=function(_14){if(this.regExp){return this.regExp.test(_14.title)||this.regExp.test(_14.text);}var n=this.terms.length;if(n==0){return false;}var _16=this.terms[0].matchesTiddler(_14);for(var i=1;i<this.terms.length;i++){if(this.terms[i-1].orFollows){if(!_16){_16|=this.terms[i].matchesTiddler(_14);}}else{if(_16){_16&=this.terms[i].matchesTiddler(_14);}}}return _16;};me.getOnlyMatchTitleQuery=function(){if(!this.onlyMatchTitleQuery){this.onlyMatchTitleQuery=new STQ(this.queryText,this.caseSensitive,true,this.useRegExp);}return this.onlyMatchTitleQuery;};me.getMarkRegExp=function(){if(this.regExp){return "".search(this.regExp)>=0?null:this.regExp;}var _18={};var n=this.terms.length;for(var i=0;i<this.terms.length;i++){var _1b=this.terms[i];if(!_1b.negate){_18[_1b.text]=true;}}var _1c=[];for(var t in _18){_1c.push("("+t.escapeRegExp()+")");}if(_1c.length==0){return null;}var _1e=_1c.join("|");return new RegExp(_1e,this.caseSensitive?"mg":"img");};me.toString=function(){if(this.regExp){return this.regExp.toString();}var _1f="";for(var i=0;i<this.terms.length;i++){_1f+=this.terms[i].toString();}return _1f;};STQ.Term=function(_21,_22,_23,_24,_25,_26,_27,_28){this.text=_21;this.inTitle=_22;this.inText=_23;this.inTag=_24;this.negate=_25;this.orFollows=_26;this.caseSensitive=_27;this.wordMatch=_28;var _29=_21.escapeRegExp();if(this.wordMatch){_29="\s\sb"+_29+"\s\sb";}this.regExp=new RegExp(_29,"m"+(_27?"":"i"));};STQ.Term.prototype.toString=function(){return (this.negate?"-":"")+(this.inTitle?"!":"")+(this.inText?"%":"")+(this.inTag?"#":"")+(this.wordMatch?"=":"")+"\s""+this.text+"\s""+(this.orFollows?" OR ":" AND ");};STQ.Term.prototype.matchesTiddler=function(_2a){if(!_2a){return false;}if(this.inTitle&&this.regExp.test(_2a.title)){return !this.negate;}if(this.inText&&this.regExp.test(_2a.text)){return !this.negate;}if(this.inTag){var _2b=_2a.tags;if(_2b){for(var i=0;i<_2b.length;i++){if(this.regExp.test(_2b[i])){return !this.negate;}}}}return this.negate;};var stringToInt=function(s,_2e){if(!s){return _2e;}var n=parseInt(s);return (n==NaN)?_2e:n;};var getIntAttribute=function(_30,_31,_32){return stringToInt(_30.getAttribute(_31));};var isDescendantOrSelf=function(_33,e){while(e!=null){if(_33==e){return true;}e=e.parentNode;}return false;};var getMatchCount=function(s,re){var m=s.match(re);return m?m.length:0;};var createEllipsis=function(_38){var e=createTiddlyElement(_38,"span");e.innerHTML="…";};var isWordChar=function(c){return (c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var getWordBounds=function(s,_3c){if(!isWordChar(s[_3c])){return null;}for(var i=_3c-1;i>=0&&isWordChar(s[i]);i--){}var _3e=i+1;var n=s.length;for(i=_3c+1;i<n&&isWordChar(s[i]);i++){}return {start:_3e,end:i};};var removeTextDecoration=function(s){var _41=["''","{{{","}}}","//","<<<","/***","***/"];var _42="";for(var i=0;i<_41.length;i++){if(i!=0){_42+="|";}_42+="("+_41[i].escapeRegExp()+")";}return s.replace(new RegExp(_42,"mg"),"").trim();};var logText="";var lastLogTime=null;var logMessage=function(_44,s){var now=new Date();var _47=lastLogTime?(now-lastLogTime).toString():"";logText+="<tr><td>"+now.convertToYYYYMMDDHHMMSSMMM()+"</td><td align='right'>"+_47+"</td><td>"+_44+"</td><td>"+s.htmlEncode()+"</td></tr>\sn";lastLogTime=now;};function writeLog(){var t=" <<JsDoIt 'WriteLog' 'WriteLog' 'javascript:writeLog();story.closeTiddler(\s"Log\s");story.displayTiddler(null,\s"Log\s");'>>"+"<html><table><tbody><tr><th>Time</th><th>Delta (ms)</th><th>Kind</th><th>Message</th></tr>\sn"+logText+"</tbody></table></html>";store.saveTiddler("Log","Log",t,config.options.txtUserName,new Date(),["System","Log"]);logText="";lastLogTime=null;}var yourSearchResultID="yourSearchResult";var yourSearchResultItemsID="yourSearchResultItems";var maxCharsInTitle=80;var maxCharsInTags=50;var maxCharsInText=250;var maxPagesInNaviBar=10;var itemsPerPageDefault=25;var itemsPerPageWithPreviewDefault=10;var minMatchWithContextSize=40;var maxMovementForWordCorrection=4;var matchInTitleWeight=4;var precisionInTitleWeight=10;var matchInTagsWeight=2;var resultElement;var lastResults;var lastQuery;var lastSearchText;var searchInputField;var searchButton;var firstIndexOnPage=0;var currentTiddler;var indexInPage;var indexInResult;var getItemsPerPage=function(){var n=(config.options.chkPreviewText)?stringToInt(config.options.txtItemsPerPageWithPreview,itemsPerPageWithPreviewDefault):stringToInt(config.options.txtItemsPerPage,itemsPerPageDefault);return (n>0)?n:1;};var standardRankFunction=function(_4a,_4b){var _4c=_4b.getMarkRegExp();if(!_4c){return 1;}var _4d=_4a.title.match(_4c);var _4e=_4d?_4d.length:0;var _4f=getMatchCount(_4a.getTags(),_4c);var _50=_4d?_4d.join("").length:0;var _51=_4a.title.length>0?_50/_4a.title.length:0;var _52=_4e*matchInTitleWeight+_4f*matchInTagsWeight+_51*precisionInTitleWeight+1;return _52;};var findMatches=function(_53,_54,_55,_56,_57,_58){lastSearchText=_54;var _59=_53.reverseLookup("tags",_58,false);var _5a=new STQ(_54,_55,false,_56);lastQuery=_5a;var _5b=_5a.getMatchingTiddlers(_59);var _5c=abego.YourSearch.getRankFunction();for(var i=0;i<_5b.length;i++){var _5e=_5b[i];var _5f=_5c(_5e,_5a);_5e.searchRank=_5f;}if(!_57){_57="title";}var _60=function(a,b){var _63=a.searchRank-b.searchRank;if(_63==0){if(a[_57]==b[_57]){return (0);}else{return (a[_57]<b[_57])?-1:+1;}}else{return (_63>0)?-1:+1;}};_5b.sort(_60);lastResults=_5b;return _5b;};var moveToWordBorder=function(s,_65,_66){var _67;if(_66){_67=getWordBounds(s,_65);}else{if(_65<=0){return _65;}_67=getWordBounds(s,_65-1);}if(!_67){return _65;}if(_66){if(_67.start>=_65-maxMovementForWordCorrection){return _67.start;}if(_67.end<=_65+maxMovementForWordCorrection){return _67.end;}}else{if(_67.end<=_65+maxMovementForWordCorrection){return _67.end;}if(_67.start>=_65-maxMovementForWordCorrection){return _67.start;}}return _65;};var getContextRangeAround=function(s,_69,_6a,_6b,_6c){var _6d=Math.max(Math.floor(_6c/(_6b+1)),minMatchWithContextSize);var _6e=Math.max(_6d-(_6a-_69),0);var _6f=Math.min(Math.floor(_6a+_6e/3),s.length);var _70=Math.max(_6f-_6d,0);_70=moveToWordBorder(s,_70,true);_6f=moveToWordBorder(s,_6f,false);return {start:_70,end:_6f};};var getTextAndMatchArray=function(s,_72){var _73=[];if(_72){var _74=0;var n=s.length;var _76=0;do{_72.lastIndex=_74;var _77=_72.exec(s);if(_77){if(_74<_77.index){var t=s.substring(_74,_77.index);_73.push({text:t});}_73.push({text:_77[0],isMatch:true});_74=_77.index+_77[0].length;}else{_73.push({text:s.substr(_74)});break;}}while(true);}else{_73.push({text:s});}return _73;};var simpleCreateLimitedTextWithMarks=function(_79,s,_7b){if(!lastQuery){return;}var _7c=getTextAndMatchArray(s,lastQuery.getMarkRegExp());var _7d=0;for(var i=0;i<_7c.length&&_7d<_7b;i++){var t=_7c[i];var _80=t.text;if(t.isMatch){createTiddlyElement(_79,"span",null,"marked",_80);}else{var _81=_7b-_7d;if(_81<_80.length){_80=_80.substring(0,_81)+"...";}createTiddlyText(_79,_80);}_7d+=_80.length;}};var addRange=function(_82,_83,_84){var n=_82.length;if(n==0){_82.push({start:_83,end:_84});return;}var i=0;for(;i<n;i++){var _87=_82[i];if(_87.start<=_84&&_83<=_87.end){var r;var _89=i+1;for(;_89<n;_89++){r=_82[_89];if(r.start>_84||_83>_87.end){break;}}var _8a=_83;var _8b=_84;for(var j=i;j<_89;j++){r=_82[j];_8a=Math.min(_8a,r.start);_8b=Math.max(_8b,r.end);}_82.splice(i,_89-i,{start:_8a,end:_8b});return;}if(_87.start>_84){break;}}_82.splice(i,0,{start:_83,end:_84});};var getTotalRangesSize=function(_8d){var _8e=0;for(var i=0;i<_8d.length;i++){var _90=_8d[i];_8e+=_90.end-_90.start;}return _8e;};var writeTextAndMatchRange=function(_91,s,_93,_94,_95){var t;var _97;var pos=0;var i=0;var _9a=0;for(;i<_93.length;i++){t=_93[i];_97=t.text;if(_94<pos+_97.length){_9a=_94-pos;break;}pos+=_97.length;}var _9b=_95-_94;for(;i<_93.length&&_9b>0;i++){t=_93[i];_97=t.text.substr(_9a);_9a=0;if(_97.length>_9b){_97=_97.substr(0,_9b);}if(t.isMatch){createTiddlyElement(_91,"span",null,"marked",_97);}else{createTiddlyText(_91,_97);}_9b-=_97.length;}if(_95<s.length){createEllipsis(_91);}};var getMatchedTextCount=function(_9c){var _9d=0;for(var i=0;i<_9c.length;i++){if(_9c[i].isMatch){_9d++;}}return _9d;};var getMatchedTextWithContextRanges=function(_9f,s,_a1){var _a2=[];var _a3=getMatchedTextCount(_9f);var pos=0;for(var i=0;i<_9f.length;i++){var t=_9f[i];var _a7=t.text;if(t.isMatch){var _a8=getContextRangeAround(s,pos,pos+_a7.length,_a3,_a1);addRange(_a2,_a8.start,_a8.end);}pos+=_a7.length;}return _a2;};var fillUpRanges=function(s,_aa,_ab){var _ac=_ab-getTotalRangesSize(_aa);while(_ac>0){if(_aa.length==0){addRange(_aa,0,moveToWordBorder(s,_ab,false));return;}else{var _ad=_aa[0];var _ae;var _af;if(_ad.start==0){_ae=_ad.end;if(_aa.length>1){_af=_aa[1].start;}else{addRange(_aa,_ae,moveToWordBorder(s,_ae+_ac,false));return;}}else{_ae=0;_af=_ad.start;}var _b0=Math.min(_af,_ae+_ac);addRange(_aa,_ae,_b0);_ac-=(_b0-_ae);}}};var writeRanges=function(_b1,s,_b3,_b4,_b5){if(_b4.length==0){return;}if(_b4[0].start>0){createEllipsis(_b1);}var _b6=_b5;for(var i=0;i<_b4.length&&_b6>0;i++){var _b8=_b4[i];var len=Math.min(_b8.end-_b8.start,_b6);writeTextAndMatchRange(_b1,s,_b3,_b8.start,_b8.start+len);_b6-=len;}};var createLimitedTextWithMarksAndContext=function(_ba,s,_bc){if(!lastQuery){return;}if(s.length<_bc){_bc=s.length;}var _bd=getTextAndMatchArray(s,lastQuery.getMarkRegExp());var _be=getMatchedTextWithContextRanges(_bd,s,_bc);fillUpRanges(s,_be,_bc);writeRanges(_ba,s,_bd,_be,_bc);};var createLimitedTextWithMarks=function(_bf,s,_c1){return createLimitedTextWithMarksAndContext(_bf,s,_c1);};var myStorySearch=function(_c2,_c3,_c4){highlightHack=new RegExp(_c4?_c2:_c2.escapeRegExp(),_c3?"mg":"img");var _c5=findMatches(store,_c2,_c3,_c4,"title","excludeSearch");firstIndexOnPage=0;showResult();highlightHack=null;};var myMacroSearchHandler=function(_c6,_c7,_c8){var _c9="";var _ca=null;var _cb=function(txt){if(config.options.chkUseYourSearch){myStorySearch(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}_c9=txt.value;};var _cd=function(e){_cb(searchInputField);return false;};var _cf=function(e){if(!e){var e=window.event;}switch(e.keyCode){case 13:_cb(this);break;case 27:if(isResultOpen()){closeResult();}else{this.value="";clearMessage();}break;}if(String.fromCharCode(e.keyCode)==this.accessKey||e.altKey){reopenResultIfApplicable();}if(this.value.length<3&&_ca){clearTimeout(_ca);}if((this.value.length>2)&&(this.value!=_c9)){if(!config.options.chkUseYourSearch||config.options.chkSearchAsYouType){if(_ca){clearTimeout(_ca);}var txt=this;_ca=setTimeout(function(){_cb(txt);},500);}}if(this.value.length==0){closeResult();}};var _d3=function(e){this.select();reopenResultIfApplicable();};var btn=createTiddlyButton(_c6,this.label,this.prompt,_cd);var txt=createTiddlyElement(_c6,"input",null,null,null);if(_c8[0]){txt.value=_c8[0];}txt.onkeyup=_cf;txt.onfocus=_d3;txt.setAttribute("size",this.sizeTextbox);txt.setAttribute("accessKey",this.accessKey);txt.setAttribute("autocomplete","off");if(config.browser.isSafari){txt.setAttribute("type","search");txt.setAttribute("results","5");}else{txt.setAttribute("type","text");}searchInputField=txt;searchButton=btn;};var isResultOpen=function(){return resultElement!=null&&resultElement.parentNode==document.body;};var closeResult=function(){if(isResultOpen()){document.body.removeChild(resultElement);}};var openAllFoundTiddlers=function(){closeResult();if(lastResults){var _d7=[];for(var i=0;i<lastResults.length;i++){_d7.push(lastResults[i].title);}story.displayTiddlers(null,_d7);}};var refreshResult=function(){if(!resultElement||!searchInputField){return;}var _d9=store.getTiddlerText("YourSearchResultTemplate");if(!_d9){_d9="<b>Tiddler YourSearchResultTemplate not found</b>";}resultElement.innerHTML=_d9;firstIndexOnPage=Math.floor(firstIndexOnPage/getItemsPerPage())*getItemsPerPage();applyHtmlMacros(resultElement,null);refreshElements(resultElement,null);if(lastResults&&lastResults.length>0){var _da=store.getTiddlerText("YourSearchItemTemplate");if(!_da){alertAndThrow("YourSearchItemTemplate not found");}var _db=document.getElementById(yourSearchResultItemsID);if(!_db){_db=createTiddlyElement(resultElement,"div",yourSearchResultItemsID);}var _dc=Math.min(firstIndexOnPage+getItemsPerPage(),lastResults.length);indexInPage=-1;for(var i=firstIndexOnPage;i<_dc;i++){currentTiddler=lastResults[i];indexInPage++;indexInResult=i;var _de=createTiddlyElement(_db,"div",null,"yourSearchItem");_de.innerHTML=_da;applyHtmlMacros(_de,null);refreshElements(_de,null);}}currentTiddler=null;ensureResultIsDisplayedNicely();};var ensureResultIsDisplayedNicely=function(){adjustResultPositionAndSize();scrollVisible();};var scrollVisible=function(){if(resultElement){window.scrollTo(0,ensureVisible(resultElement));}if(searchInputField){window.scrollTo(0,ensureVisible(searchInputField));}};var adjustResultPositionAndSize=function(){if(!searchInputField){return;}var _df=searchInputField;var _e0=findPosX(_df);var _e1=findPosY(_df);var _e2=_df.offsetHeight;var _e3=_e0;var _e4=_e1+_e2;var _e5=findWindowWidth();if(_e5<resultElement.offsetWidth){resultElement.style.width=(_e5-100)+"px";_e5=findWindowWidth();}var _e6=resultElement.offsetWidth;if(_e3+_e6>_e5){_e3=_e5-_e6-30;}if(_e3<0){_e3=0;}resultElement.style.left=_e3+"px";resultElement.style.top=_e4+"px";resultElement.style.display="block";};var showResult=function(){if(!resultElement){resultElement=createTiddlyElement(document.body,"div",yourSearchResultID,"yourSearchResult");}else{if(resultElement.parentNode!=document.body){document.body.appendChild(resultElement);}}refreshResult();};var reopenResultIfApplicable=function(){if(searchInputField==null||!config.options.chkUseYourSearch){return;}if((searchInputField.value==lastSearchText)&&lastSearchText&&!isResultOpen()){if(resultElement&&(resultElement.parentNode!=document.body)){document.body.appendChild(resultElement);ensureResultIsDisplayedNicely();}else{showResult();}}};var setFirstIndexOnPage=function(_e7){if(!lastResults||lastResults.length==0){return;}firstIndexOnPage=Math.min(Math.max(0,_e7),lastResults.length-1);refreshResult();};var onDocumentClick=function(e){if(e.target==searchInputField){return;}if(e.target==searchButton){return;}if(resultElement&&isDescendantOrSelf(resultElement,e.target)){return;}closeResult();};var onDocumentKeyup=function(e){if(e.keyCode==27){closeResult();}};addEvent(document,"click",onDocumentClick);addEvent(document,"keyup",onDocumentKeyup);config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",funcs:{},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return lastResults&&lastResults.length>0;},"previewText":function(){return config.options.chkPreviewText;}}};config.macros.yourSearch.handler=function(_ea,_eb,_ec,_ed,_ee,_ef){if(_ec.length==0){return;}var _f0=_ec[0];var _f1=config.macros.yourSearch.funcs[_f0];if(_f1){_f1(_ea,_eb,_ec,_ed,_ee,_ef);}};config.macros.yourSearch.funcs.itemRange=function(_f2){if(lastResults){var _f3=Math.min(firstIndexOnPage+getItemsPerPage(),lastResults.length);var s="%0 - %1".format([firstIndexOnPage+1,_f3]);createTiddlyText(_f2,s);}};config.macros.yourSearch.funcs.count=function(_f5){if(lastSearchText){createTiddlyText(_f5,lastResults.length.toString());}};config.macros.yourSearch.funcs.query=function(_f6){if(lastResults){createTiddlyText(_f6,lastSearchText);}};config.macros.yourSearch.funcs.version=function(_f7){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_f7,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">"+t+"<font>";};config.macros.yourSearch.funcs.copyright=function(_fa){var e=createTiddlyElement(_fa,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\s"black\s" face=\s"Arial, Helvetica, sans-serif\s">© 2005-2006 <b><font color=\s"red\s">abego</font></b> Software<font>";};config.macros.yourSearch.funcs.linkButton=function(_fc,_fd,_fe,_ff,_100,_101){if(_fe<2){return;}var _102=_fe[1];var text=_fe<3?_102:_fe[2];var _104=_fe<4?text:_fe[3];var _105=_fe<5?null:_fe[4];var btn=createTiddlyButton(_fc,text,_104,closeResultAndDisplayTiddler,null,null,_105);btn.setAttribute("tiddlyLink",_102);};config.macros.yourSearch.funcs.closeButton=function(_107,_108,_109,_10a,_10b,_10c){var _10d=createTiddlyButton(_107,"close","Close the Search Results (Shortcut: ESC)",closeResult);};config.macros.yourSearch.funcs.openAllButton=function(_10e,_10f,_110,_111,_112,_113){if(!lastResults){return;}var n=lastResults.length;if(n==0){return;}var _115=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _116=createTiddlyButton(_10e,_115,"Open all found tiddlers (Shortcut: Alt-O)",openAllFoundTiddlers);_116.setAttribute("accessKey","O");};var onNaviButtonClick=function(e){if(!e){var e=window.event;}var _119=getIntAttribute(this,"page");setFirstIndexOnPage(_119*getItemsPerPage(),0);};config.macros.yourSearch.funcs.naviBar=function(_11a,_11b,_11c,_11d,_11e,_11f){if(!lastResults||lastResults.length==0){return;}var _120;var _121=Math.floor(firstIndexOnPage/getItemsPerPage());var _122=Math.floor((lastResults.length-1)/getItemsPerPage());if(_121>0){_120=createTiddlyButton(_11a,"Previous","Go to previous page (Shortcut: Alt-'<')",onNaviButtonClick,"prev");_120.setAttribute("page",(_121-1).toString());_120.setAttribute("accessKey","<");}for(var i=-maxPagesInNaviBar;i<maxPagesInNaviBar;i++){var _124=_121+i;if(_124<0){continue;}if(_124>_122){break;}var _125=(i+_121+1).toString();var _126=_124==_121?"currentPage":"otherPage";_120=createTiddlyButton(_11a,_125,"Go to page %0".format([_125]),onNaviButtonClick,_126);_120.setAttribute("page",(_124).toString());}if(_121<_122){_120=createTiddlyButton(_11a,"Next","Go to next page (Shortcut: Alt-'>')",onNaviButtonClick,"next");_120.setAttribute("page",(_121+1).toString());_120.setAttribute("accessKey",">");}};config.macros.yourSearch.funcs["if"]=function(_127,_128,_129,_12a,_12b,_12c){if(_129.length<2){return;}var _12d=_129[1];var _12e=(_12d=="not");if(_12e){if(_129.length<3){return;}_12d=_129[2];}var test=config.macros.yourSearch.tests[_12d];var _130=false;try{if(test){_130=test(_127,_128,_129,_12a,_12b,_12c)!=_12e;}else{_130=(!eval(_12d))==_12e;}}catch(ex){}if(!_130){_127.style.display="none";}};var createOptionWithRefresh=function(_131,_132,_133,_134){invokeMacro(_131,"option",_132,_133,_134);var elem=_131.lastChild;var _136=elem.onclick;elem.onclick=function(e){var _138=_136.apply(this,arguments);refreshResult();return _138;};return elem;};config.macros.yourSearch.funcs.chkPreviewText=function(_139,_13a,_13b,_13c,_13d,_13e){var _13f=_13b.slice(1).join(" ");var elem=createOptionWithRefresh(_139,"chkPreviewText",_13c,_13e);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",funcs:{}};config.macros.foundTiddler.handler=function(_141,_142,_143,_144,_145,_146){if(!currentTiddler){return;}var name=_143[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_141,_142,_143,_144,_145,_146);}};var closeResultAndDisplayTiddler=function(e){closeResult();var _14a=this.getAttribute("tiddlyLink");if(_14a){var _14b=this.getAttribute("withHilite");var _14c=highlightHack;if(_14b&&_14b=="true"&&lastQuery){highlightHack=lastQuery.getMarkRegExp();}story.displayTiddler(this,_14a);highlightHack=_14c;}return (false);};var getShortCutNumber=function(){if(!currentTiddler){return -1;}if(indexInPage>=0&&indexInPage<=9){return indexInPage<9?(indexInPage+1):0;}else{return -1;}};config.macros.foundTiddler.funcs.title=function(_14d,_14e,_14f,_150,_151,_152){if(!currentTiddler){return;}var _153=getShortCutNumber();var _154=_153>=0?"Open tiddler (Shortcut: Alt-%0)".format([_153.toString()]):"Open tiddler";var btn=createTiddlyButton(_14d,null,_154,closeResultAndDisplayTiddler,null);btn.setAttribute("tiddlyLink",currentTiddler.title);btn.setAttribute("withHilite","true");createLimitedTextWithMarks(btn,currentTiddler.title,maxCharsInTitle);if(_153>=0){btn.setAttribute("accessKey",_153.toString());}};config.macros.foundTiddler.funcs.tags=function(_156,_157,_158,_159,_15a,_15b){if(!currentTiddler){return;}createLimitedTextWithMarks(_156,currentTiddler.getTags(),maxCharsInTags);};config.macros.foundTiddler.funcs.text=function(_15c,_15d,_15e,_15f,_160,_161){if(!currentTiddler){return;}createLimitedTextWithMarks(_15c,removeTextDecoration(currentTiddler.text),maxCharsInText);};config.macros.foundTiddler.funcs.number=function(_162,_163,_164,_165,_166,_167){var _168=getShortCutNumber();if(_168>=0){var text="%0)".format([_168.toString()]);createTiddlyElement(_162,"span",null,"shortcutNumber",text);}};function scrollToAnchor(name){return false;}if(config.options.chkUseYourSearch==undefined){config.options.chkUseYourSearch=true;}if(config.options.chkPreviewText==undefined){config.options.chkPreviewText=true;}if(config.options.chkSearchAsYouType==undefined){config.options.chkSearchAsYouType=true;}if(config.options.chkSearchInTitle==undefined){config.options.chkSearchInTitle=true;}if(config.options.chkSearchInText==undefined){config.options.chkSearchInText=true;}if(config.options.chkSearchInTags==undefined){config.options.chkSearchInTags=true;}if(config.options.txtItemsPerPage==undefined){config.options.txtItemsPerPage=itemsPerPageDefault;}if(config.options.txtItemsPerPageWithPreview==undefined){config.options.txtItemsPerPageWithPreview=itemsPerPageWithPreviewDefault;}config.shadowTiddlers.AdvancedOptions+="\sn<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]])//";config.shadowTiddlers["YourSearch Introduction"]="!About YourSearch\sn"+"\sn"+"YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!\sn"+"\sn"+"''May the '~Alt-F' be with you.''\sn"+"\sn"+"\sn"+"!Features\sn"+"* YourSearch searches for tiddlers that match your query ''as you type'' into the 'search' field. It presents a list of the ''\s"Top Ten\s"'' tiddlers in a ''popup-like window'': the ''[[YourSearch Result]]''. The tiddlers currently displayed in your TiddlyWiki are not affected.\sn"+"* Using ''~TiddlerRank technology'' the [[YourSearch Result]] lists the ''most interesting tiddlers first''.\sn"+"* Through ''Filtered Search'' and ''Boolean Search'' you can easily refining your search, like excluding words or searching for multiple words. This way less tiddlers are displayed in the [[YourSearch Result]] and you can faster scan the result for the tiddler you are looking for.\sn"+"* The [[YourSearch Result]] lists the found tiddlers ''page-wise'', e.g. 10 per page. Use the ''Result Page Navigation Bar'' to navigate between pages if the result does not fit on one page.\sn"+"* The [[YourSearch Result]] states the ''total number of found tiddlers''. This way you can quickly decide if you want to browse the result list or if you want to refine your search first to shorten the result list.\sn"+"* Beside the ''title of the found tiddlers'' the [[YourSearch Result]] also ''displays tags'' and ''tiddler text previews''. The ''tiddler text preview'' is an extract of the tiddler's content, showing the most interesting parts related to your query (e.g. the texts around the words you are looking for).\sn"+"* The words you are looking for are hilited in the titles, tags and text previews of the [[YourSearch Result]].\sn"+"* If you are not interested in the tiddler text previews but prefer to get longer lists of tiddlers on one result page you may ''switch of the text preview''.\sn"+"* If the [[YourSearch Result]] contains the tiddler you are looking for you can just ''click its title to display'' it in your TiddlyWiki. Alternatively you may also ''open all found tiddlers'' at once. \sn"+"* Use [[YourSearch Options]] to customize YourSearch to your needs. E.g. depending on the size of your screen you may change the number of tiddlers displayed in the [[YourSearch Result]]. In the [[YourSearch Options]] and the AdvancedOptions you may also switch off YourSearch in case you temporarily want to use the standard search.\sn"+"* For the most frequently actions ''access keys'' are defined so you can perform your search without using the mouse.\sn"+"\sn";config.shadowTiddlers["YourSearch Help"]="<<tiddler [[YourSearch Introduction]]>>"+"\sn"+"!Filtered Search<html><a name='Filtered'/></html>\sn"+"Using the Filtered Search you can restrict your search to certain parts of a tiddler, e.g only search the tags or only the titles.\sn"+"|!What you want|!What you type|!Example|\sn"+"|Search ''titles only''|start word with ''!''|{{{!jonny}}}|\sn"+"|Search ''contents only''|start word with ''%''|{{{%football}}}|\sn"+"|Search ''tags only''|start word with ''#''|{{{#Plugin}}}|\sn"+"\sn"+"You may use more than one filter for a word. E.g. {{{!#Plugin}}} finds tiddlers containing \s"Plugin\s" either in the title or in the tags (but does not look for \s"Plugin\s" in the content).\sn"+"\sn"+"!Boolean Search<html><a name='Boolean'/></html>\sn"+"The Boolean Search is useful when searching for multiple words.\sn"+"|!What you want|!What you type|!Example|\sn"+"|''All words'' must exist|List of words|{{{jonny jeremy}}}|\sn"+"|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\sn"+"|A word ''must not exist''|Start word with ''-''|{{{-jonny}}}|\sn"+"\sn"+"''Note:'' When you specify two words, separated with a space, YourSearch finds all tiddlers that contain both words, but not necessarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need to put the words into quotes. I.e. you type: {{{\s"john brown\s"}}}.\sn"+"\sn"+"!'Exact Word' Search<html><a name='Exact'/></html>\sn"+"By default a search result all matches that 'contain' the searched text. \sn"+" E.g. if you search for 'Task' you will get all tiddlers containing 'Task', but also 'CompletedTask', 'TaskForce' etc.\sn"+"\sn"+"If you only want to get the tiddlers that contain 'exactly the word' you need to prefix it with a '='. E.g. typing '=Task' will the tiddlers that contain the word 'Task', ignoring words that just contain 'Task' as a substring.\sn"+"\sn"+"!Combined Search<html><a name='Combined'/></html>\sn"+"You are free to combine the various search options. \sn"+"\sn"+"''Examples''\sn"+"|!What you type|!Result|\sn"+"|{{{!jonny !jeremy -%football}}}| all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its titles, but no {{{football}}} in content.|\sn"+"|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact word). Tags named 'CompletedTask', 'TaskForce' etc. are not considered.|\sn"+"\sn"+"!~CaseSensitiveSearch and ~RegExpSearch<html><a name='Case'/></html>\sn"+"The standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearch. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\sn"+"\sn"+"!Access Keys<html><a name='Access'/></html>\sn"+"You are encouraged to use the access keys (also called \s"shortcut\s" keys) for the most frequently used operations. For quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\sn"+"\sn"+"|!Key|!Operation|\sn"+"|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search input field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the previous search result. This way you can quickly display multiple tiddlers using \s"Press {{{Alt-F}}}. Select tiddler.\s" sequences.|\sn"+"|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Result]] is already closed and the cursor is in the search input field the field's content is cleared so you start a new query.|\sn"+"|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second etc. tiddler from the result list.|\sn"+"|{{{Alt-O}}}|Opens all found tiddlers.|\sn"+"|{{{Alt-P}}}|Toggles the 'Preview Text' mode.|\sn"+"|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[YourSearch Result]].|\sn"+"|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the {{{Return}}} key actually starts the search (as does pressing the 'search' button).|\sn"+"\sn";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\sn"+"|>|<<option chkUseYourSearch>> Use 'Your Search'|\sn"+"|!|<<option chkPreviewText>> Show Text Preview|\sn"+"|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required to start search)|\sn"+"|!|Default Search Filter:<<option chkSearchInTitle>>Titles ('!') <<option chkSearchInText>>Texts ('%') <<option chkSearchInTags>>Tags ('#') <html><br><font size=\s"-2\s">The parts of a tiddlers that are searched when you don't explicitly specify a filter in the search text (using a '!', '%' or '#' prefix).</font></html>|\sn"+"|!|Number of items on search result page: <<option txtItemsPerPage>>|\sn"+"|!|Number of items on search result page with preview text: <<option txtItemsPerPageWithPreview>>|\sn";config.shadowTiddlers["YourSearchStyleSheet"]="/***\sn"+"!~YourSearchResult Stylesheet\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult {\sn"+"\stposition: absolute;\sn"+"\stwidth: 800px;\sn"+"\sn"+"\stpadding: 0.2em;\sn"+"\stlist-style: none;\sn"+"\stmargin: 0;\sn"+"\sn"+"\stbackground: White;\sn"+"\stborder: 1px solid DarkGray;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Summary Section\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult .summary {\sn"+"\stborder-bottom-width: thin;\sn"+"\stborder-bottom-style: solid;\sn"+"\stborder-bottom-color: #999999;\sn"+"\stpadding-bottom: 4px;\sn"+"}\sn"+"\sn"+".yourSearchRange, .yourSearchCount, .yourSearchQuery {\sn"+"\stfont-weight: bold;\sn"+"}\sn"+"\sn"+".yourSearchResult .summary .button {\sn"+"\stfont-size: 10px;\sn"+"\sn"+"\stpadding-left: 0.3em;\sn"+"\stpadding-right: 0.3em;\sn"+"}\sn"+"\sn"+".yourSearchResult .summary .chkBoxLabel {\sn"+"\stfont-size: 10px;\sn"+"\sn"+"\stpadding-right: 0.3em;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Items Area\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchResult .marked {\sn"+"\stbackground: none;\sn"+"\stfont-weight: bold;\sn"+"}\sn"+"\sn"+".yourSearchItem {\sn"+"\stmargin-top: 2px;\sn"+"}\sn"+"\sn"+".yourSearchNumber {\sn"+"\stcolor: #808080;\sn"+"}\sn"+"\sn"+"\sn"+".yourSearchTags {\sn"+"\stcolor: #008000;\sn"+"}\sn"+"\sn"+".yourSearchText {\sn"+"\stcolor: #808080;\sn"+"\stmargin-bottom: 6px;\sn"+"}\sn"+"\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Footer\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchFooter {\sn"+"\stmargin-top: 8px;\sn"+"\stborder-top-width: thin;\sn"+"\stborder-top-style: solid;\sn"+"\stborder-top-color: #999999;\sn"+"}\sn"+"\sn"+".yourSearchFooter a:hover{\sn"+"\stbackground: none;\sn"+"\stcolor: none;\sn"+"}\sn"+"/*}}}*/\sn"+"/***\sn"+"!!Navigation Bar\sn"+"***/\sn"+"/*{{{*/\sn"+".yourSearchNaviBar a {\sn"+"\stfont-size: 16px;\sn"+"\stmargin-left: 4px;\sn"+"\stmargin-right: 4px;\sn"+"\stcolor: black;\sn"+"\sttext-decoration: underline;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar a:hover {\sn"+"\stbackground-color: none;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .prev {\sn"+"\stfont-weight: bold;\sn"+"\stcolor: blue;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .currentPage {\sn"+"\stcolor: #FF0000;\sn"+"\stfont-weight: bold;\sn"+"\sttext-decoration: none;\sn"+"}\sn"+"\sn"+".yourSearchNaviBar .next {\sn"+"\stfont-weight: bold;\sn"+"\stcolor: blue;\sn"+"}\sn"+"/*}}}*/\sn";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<span macro=\s"yourSearch if found\s">\sn"+"<!-- The Summary Header ============================================ -->\sn"+"<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stYourSearch Result <span class=\s"yourSearchRange\s" macro=\s"yourSearch itemRange\s"></span>\sn"+"\st\st of <span class=\s"yourSearchCount\s" macro=\s"yourSearch count\s"></span>\sn"+"\st\stfor <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>\sn"+"\st</td>\sn"+"\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+"\st\st<span macro=\s"yourSearch chkPreviewText\s"></span><span class=\s"chkBoxLabel\s">preview text</span>\sn"+"\st\st<span macro=\s"yourSearch openAllButton\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"\sn"+"<!-- The List of Found Tiddlers ============================================ -->\sn"+"<div id=\s"yourSearchResultItems\s" itemsPerPage=\s"25\s" itemsPerPageWithPreview=\s"10\s"></div>\sn"+"\sn"+"<!-- The Footer (with the Navigation) ============================================ -->\sn"+"<table class=\s"yourSearchFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stResult page: <span class=\s"yourSearchNaviBar\s" macro=\s"yourSearch naviBar\s"></span>\sn"+"\st</td>\sn"+"\st<td align=\s"right\s"><span macro=\s"yourSearch version\s"></span>, <span macro=\s"yourSearch copyright\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"<!-- end of the 'tiddlers found' case =========================================== -->\sn"+"</span>\sn"+"\sn"+"\sn"+"<!-- The \s"No tiddlers found\s" case =========================================== -->\sn"+"<span macro=\s"yourSearch if not found\s">\sn"+"<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+" <tr>\sn"+"\st<td align=\s"left\s">\sn"+"\st\stYourSearch Result: No tiddlers found for <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>.\sn"+"\st</td>\sn"+"\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+"\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+"\st</td>\sn"+" </tr>\sn"+"</tbody></table>\sn"+"</span>\sn"+"\sn"+"\sn"+"<!--\sn"+"}}}\sn"+"-->\sn";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\sn"+"{{{\sn"+"-->\sn"+"<span class='yourSearchNumber' macro='foundTiddler number'></span>\sn"+"<span class='yourSearchTitle' macro='foundTiddler title'/></span> - \sn"+"<span class='yourSearchTags' macro='foundTiddler tags'/></span>\sn"+"<span macro=\s"yourSearch if previewText\s"><div class='yourSearchText' macro='foundTiddler text'/></div></span>\sn"+"<!--\sn"+"}}}\sn"+"-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");var origMacros_search_handler=config.macros.search.handler;config.macros.search.handler=myMacroSearchHandler;var ownsOverwrittenFunctions=function(){var _16b=(config.macros.search.handler==myMacroSearchHandler);return _16b;};var checkForOtherHijacker=function(){if(!ownsOverwrittenFunctions()){alert("Message from YourSearchPlugin:\sn\sn\sn"+"Another plugin has disabled the 'Your Search' features.\sn\sn\sn"+"You may disable the other plugin or change the load order of \sn"+"the plugins (by changing the names of the tiddlers)\sn"+"to enable the 'Your Search' features.");}};setTimeout(checkForOtherHijacker,5000);abego.YourSearch.getStandardRankFunction=function(){return standardRankFunction;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return currentTiddler;};}\n/***\n%/\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005-2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n\n
/***\n|''Name:''|YourSearchPlugin|\n|''Version:''|2.0.2 (2006-02-13)|\n|''Source:''|http://tiddlywiki.abego-software.de/#YourSearchPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|2.0|\n|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|\n<<tiddler [[YourSearch Introduction]]>>\nFor more information see [[Help|YourSearch Help]].\n\n!Compatibility\nThis plugin requires TiddlyWiki 2.0. \nUse http://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1 for older TiddlyWiki versions.\n\n!Revision history\n* v2.0.2 (2006-02-13)\n** Bugfix for Firefox 1.5.0.1 related to the "Show prefix" checkbox. Thanks to Ted Pavlic for reporting and to BramChen for fixing. \n** Internal\n*** Make "JSLint" conform\n* v2.0.1 (2006-02-05)\n** Support "Exact Word Match" (use '=' to prefix word)\n** Support default filter settings (when no filter flags are given in search term)\n** Rework on the "less than 3 chars search text" feature (thanks to EricShulman)\n** Better support SinglePageMode when doing "Open all tiddlers" (thanks to EricShulman)\n** Support Firefox 1.5.0.1\n** Bug: Fixed a hilite bug in "classic search mode" (thanks to EricShulman)\n* v2.0.0 (2006-01-16)\n** Add User Interface\n* v1.0.1 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.0 (2005-12-28)\n** initial version\n/%\n***/\n//{{{\n//============================================================================\n//============================================================================\n// YourSearchPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the Plugin is only installed once.\n//\nif (!version.extensions.YourSearchPlugin) {\n\nversion.extensions.YourSearchPlugin = {\n major: 2, minor: 0, revision: 2,\n date: new Date(2006, 2, 13), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#YourSearchPlugin"\n};\n\nvar alertAndThrow = function(msg) {alert(msg);throw msg;};\n\nif (!window.abego) window.abego = {};\nif (abego.YourSearch) alertAndThrow("abego.YourSearch already defined");\nabego.YourSearch = {};\n\nif (version.major < 2) alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.0 or newer.\sn\snGet YourSearch 1.0.1 to use YourSearch with older versions of TiddlyWiki.\sn\snhttp://tiddlywiki.abego-software.de/#YourSearchPlugin-1.0.1");\n\n//----------------------------------------------------------------------------\n// The STQ (SimpleTiddlerQuery) Class\n//----------------------------------------------------------------------------\n\n// Internal.\n// \nvar STQ = function(queryText, caseSensitive, matchTitleOnly, useRegExp) {\n this.queryText = queryText;\n this.caseSensitive = caseSensitive;\n\n if (useRegExp) {\n this.regExp = new RegExp(queryText, caseSensitive ? "mg" : "img");\n return;\n }\n \n this.terms = [];\n\n // The regular expression that matches a single search term of the form\n // (whitespace handling and grouping omitted for clarity):\n //\n // -?[#!%]*(<doubleQuoteStringLiteral>|<wordWithoutSpace>) (AND|OR)?\n //\n // group 1: '-' (negate, optional)\n // group 2: [!%#]* (may be empty)\n // group 3: String literal "..."\n // group 4: word\n // group 5: AND / OR (optional) \n //\n // (group 3 xor group 4 is defined)\n //\n var re = /\ss*(\s-)?([#%!=]*)(?:(?:("(?:(?:\s\s")|[^"])*")|(\sS+)))(?:\ss+((?:[aA][nN][dD])|(?:[oO][rR]))(?!\sS))?/mg;\n\n var matches = re.exec(queryText);\n\n while (matches != null && matches.length == 6) {\n var negate = '-' == matches[1];\n var flags = matches[2];\n var inTitle = flags.indexOf('!') >= 0;\n var inText = flags.indexOf('%') >= 0;\n var inTag = flags.indexOf('#') >= 0;\n var wordMatch = flags.indexOf('=') >= 0;\n if (!inTitle && !inText && !inTag) {\n inTitle = config.options.chkSearchInTitle;\n inText = config.options.chkSearchInText;\n inTag = config.options.chkSearchInTags;\n \n // If all settings are off (i.e. all results would be empty, \n // i.e user error or checkboxes are gone) set all settings\n if (!inTitle && !inText && !inTag) {\n inTitle = inText = inTag = true;\n }\n }\n if (matchTitleOnly) {\n inText = false;\n inTag = false;\n }\n \n var text;\n if (matches[3]) {\n //Quoted String\n try {\n text = eval(matches[3]);\n } catch (ex) {\n // ignore error. Will be handled right after this.\n }\n } else {\n text = matches[4];\n }\n if (!text) {\n throw "Invalid search expression: %0".format([queryText]);\n }\n var orFollows = matches[5] && matches[5].charAt(0).toLowerCase() == 'o';\n this.terms.push(new STQ.Term(text, inTitle, inText, inTag, negate, orFollows, caseSensitive, wordMatch));\n \n matches = re.exec(queryText);\n }\n};\n\nvar me = STQ.prototype;\n\n// Internal.\n// \n// Returns an array with those tiddlers from the tiddlersMap that \n// match the query.\n//\nme.getMatchingTiddlers = function(tiddlersMap) {\n var result = [];\n for (var i in tiddlersMap) {\n var t = tiddlersMap[i];\n if ((t instanceof Tiddler) && this.matchesTiddler(t)) {\n result.push(t);\n }\n }\n return result;\n};\n\n\n// Internal.\n// \n// Returns true if the query has a match in the given tiddler.\n//\n// @param tiddler [may be null]\n//\nme.matchesTiddler = function(tiddler) {\n if (this.regExp) {\n return this.regExp.test(tiddler.title) || this.regExp.test(tiddler.text);\n }\n \n var n = this.terms.length;\n if (n == 0) {\n return false;\n }\n \n var hasMatch = this.terms[0].matchesTiddler(tiddler);\n for (var i = 1; i < this.terms.length; i++) {\n if (this.terms[i-1].orFollows) {\n // the OR case.\n \n // shortcut: when the first operand of an OR is true \n // we don't need to evaluate the second operand since \n // the result of the OR will always be true.\n \n // In the other case we actually to the "OR"\n if (!hasMatch) {\n hasMatch |= this.terms[i].matchesTiddler(tiddler);\n }\n } else {\n // the AND case.\n \n // shortcut: when the first operand of an AND is false \n // we don't need to evaluate the second operand since\n // the result of the AND will always be false.\n \n // Otherwise we actually to the "AND"\n if (hasMatch) {\n hasMatch &= this.terms[i].matchesTiddler(tiddler);\n }\n }\n }\n return hasMatch;\n};\n\n// Internal.\n// \nme.getOnlyMatchTitleQuery = function() {\n if (!this.onlyMatchTitleQuery) {\n this.onlyMatchTitleQuery = new STQ(this.queryText, this.caseSensitive, true, this.useRegExp);\n }\n return this.onlyMatchTitleQuery;\n};\n\n\n// Returns a regular expression that can be used to marking/hiliting\n// matches in the text.\n//\n// @return [may be null] null when the query does not provide marking information.\n//\nme.getMarkRegExp = function() {\n if (this.regExp) {\n // Only use the regExp for marking when it does not match the empty string.\n return "".search(this.regExp) >= 0 ? null : this.regExp;\n }\n \n var stringSet = {};\n var n = this.terms.length;\n for (var i = 0; i < this.terms.length; i++) {\n var term = this.terms[i];\n if (!term.negate) stringSet[term.text] = true;\n }\n\n var pattern = [];\n for (var t in stringSet) pattern.push("(" + t.escapeRegExp() + ")");\n \n if (pattern.length == 0) return null;\n\n var joinedPattern = pattern.join("|");\n return new RegExp(joinedPattern, this.caseSensitive ? "mg" : "img");\n};\n\n// Internal.\n// \nme.toString = function() {\n if (this.regExp) {\n return this.regExp.toString();\n }\n \n var result = "";\n for (var i = 0; i < this.terms.length; i++) {\n result += this.terms[i].toString();\n }\n return result;\n};\n\n//----------------------------------------------------------------------------\n// The STQ.Term Class\n//----------------------------------------------------------------------------\n\n// Internal.\n//\nSTQ.Term = function(text, inTitle, inText, inTag, negate, orFollows, caseSensitive, wordMatch) {\n this.text = text;\n this.inTitle = inTitle;\n this.inText = inText;\n this.inTag = inTag;\n this.negate = negate;\n this.orFollows = orFollows;\n this.caseSensitive = caseSensitive;\n this.wordMatch = wordMatch;\n \n var reText = text.escapeRegExp();\n if (this.wordMatch) reText = "\s\sb"+reText+"\s\sb";\n this.regExp = new RegExp(reText, "m"+(caseSensitive ? "" : "i"));\n};\n\n// Internal.\n//\nSTQ.Term.prototype.toString = function() {\n return (this.negate ? "-" : "")+(this.inTitle ? "!" : "")+(this.inText? "%" : "")+(this.inTag? "#" : "")+(this.wordMatch ? "=" : "")+'"'+this.text+'"'+ (this.orFollows ? " OR " : " AND ");\n};\n\n// Internal.\n//\n// Returns true if the term has a match in the given tiddler.\n//\n// @param tiddler [may be null]\n//\nSTQ.Term.prototype.matchesTiddler = function(tiddler) {\n if (!tiddler) {\n return false;\n }\n \n if (this.inTitle && this.regExp.test(tiddler.title)) {\n return !this.negate;\n }\n if (this.inText && this.regExp.test(tiddler.text)) {\n return !this.negate;\n }\n if (this.inTag) {\n var tags = tiddler.tags;\n if (tags) {\n for (var i = 0; i < tags.length; i++) {\n if (this.regExp.test(tags[i])) {\n return !this.negate;\n }\n }\n }\n }\n \n return this.negate;\n};\n\n//----------------------------------------------------------------------------\n// Utils\n//----------------------------------------------------------------------------\n\nvar stringToInt = function(s, defaultValue) {\n if (!s) return defaultValue;\n var n = parseInt(s);\n return (n == NaN) ? defaultValue : n;\n};\n\nvar getIntAttribute = function(elem, name, defaultValue) {\n return stringToInt(elem.getAttribute(name));\n};\n\n// Returns true if e is either self or a descendant (child, grandchild,...) of self.\n//\n// @param self DOM:Element\n// @param e DOM:Element or null\n//\nvar isDescendantOrSelf = function(self, e) {\n while (e != null) {\n if (self == e) return true;\n e = e.parentNode;\n }\n return false;\n};\n\nvar getMatchCount = function(s, re) {\n var m = s.match(re);\n return m ? m.length : 0;\n};\n\nvar createEllipsis = function(place) {\n var e = createTiddlyElement(place,"span");\n e.innerHTML = "…";\n};\n\nvar isWordChar = function(c) {\n return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c == "_";\n};\n\n// Returns the bounds of the word in s around offset as a {start: , end:} object.\n//\n// Returns null when the char at offset is not a word char.\n//\nvar getWordBounds = function(s, offset) {\n // Handle the "offset is not in word" case\n if (!isWordChar(s[offset])) return null;\n\n for (var i = offset-1; i >= 0 && isWordChar(s[i]); i--) \n {/*empty*/}\n \n var startIndex = i+1;\n var n = s.length;\n for (i = offset+1; i < n && isWordChar(s[i]); i++) \n {/*empty*/}\n \n return {start: startIndex, end: i};\n};\n\n\nvar removeTextDecoration = function(s) {\n var removeThis = ["''", "{{{", "}}}", "//", "<<<", "/***", "***/"];\n var reText = "";\n for (var i = 0; i < removeThis.length; i++) {\n if (i != 0) reText += "|";\n reText += "("+removeThis[i].escapeRegExp()+")";\n }\n return s.replace(new RegExp(reText, "mg"), "").trim();\n};\n\nvar logText = "";\nvar lastLogTime = null;\nvar logMessage = function(kind, s) {\n var now = new Date();\n var delta = lastLogTime ? (now-lastLogTime).toString() : "";\n logText += "<tr><td>"+now.convertToYYYYMMDDHHMMSSMMM()+"</td><td align='right'>"+delta+"</td><td>"+kind+"</td><td>"+s.htmlEncode()+"</td></tr>\sn";\n lastLogTime = now;\n};\n\nfunction writeLog() {\n var t = " <<JsDoIt 'WriteLog' 'WriteLog' 'javascript:writeLog();story.closeTiddler(\s"Log\s");story.displayTiddler(null,\s"Log\s");'>>"+\n "<html><table><tbody><tr><th>Time</th><th>Delta (ms)</th><th>Kind</th><th>Message</th></tr>\sn" + logText + "</tbody></table></html>";\n store.saveTiddler("Log", "Log",t,config.options.txtUserName,new Date(),["System", "Log"]);\n logText = "";\n lastLogTime = null;\n}\n\n//----------------------------------------------------------------------------\n// The Search Core\n//----------------------------------------------------------------------------\n\n// Constants\n\n// DOM IDs\nvar yourSearchResultID = "yourSearchResult";\nvar yourSearchResultItemsID = "yourSearchResultItems";\n\n// Visual appearance of the result page\nvar maxCharsInTitle = 80;\nvar maxCharsInTags = 50;\nvar maxCharsInText = 250;\nvar maxPagesInNaviBar = 10; // Maximum number of pages listed in the navigation bar (before or after the current page)\n\nvar itemsPerPageDefault = 25; // Default maximum number of items on one search result page\nvar itemsPerPageWithPreviewDefault = 10; // Default maximum number of items on one search result page when PreviewText is on\n\n// Context Calculation\nvar minMatchWithContextSize = 40; \nvar maxMovementForWordCorrection = 4; // When a "match" context starts or end on a word the context borders may be changed to at most this amound to include or exclude the word.\n\n// Ranking Weights\nvar matchInTitleWeight = 4;\nvar precisionInTitleWeight = 10;\nvar matchInTagsWeight = 2;\n\n// Variables\nvar resultElement; // The (popup) DOM element containing the search result [may be null]\nvar lastResults; // Array of tiddlers that matched the last search\nvar lastQuery; // The last Search query (STQ)\nvar lastSearchText; // The last search text, as used to create the lastQuery\nvar searchInputField; // The "search" input field\nvar searchButton; // The "search" button\nvar firstIndexOnPage = 0; // The index of the first item of the lastResults list displayed on the search result page\n\nvar currentTiddler; // While creating the search result page the tiddler that is currently rendered.\nvar indexInPage; // The index (in the current page) of the tiddler currently rendered.\nvar indexInResult; // The index (in the result array) of the tiddler currently rendered.\n\n\nvar getItemsPerPage = function() {\n var n = (config.options.chkPreviewText) \n ? stringToInt(config.options.txtItemsPerPageWithPreview, itemsPerPageWithPreviewDefault) \n : stringToInt(config.options.txtItemsPerPage, itemsPerPageDefault);\n return (n > 0) ? n : 1;\n};\n\nvar standardRankFunction = function(tiddler, query) { \n // Count the matches in the title and the tags\n var markRE = query.getMarkRegExp();\n if (!markRE) return 1;\n \n var matchesInTitle = tiddler.title.match(markRE);\n var nMatchesInTitle = matchesInTitle ? matchesInTitle.length : 0;\n var nMatchesInTags = getMatchCount(tiddler.getTags(), markRE);\n\n // Calculate the "precision" of the matches in the title as the ratio of\n // the length of the matches to the total length of the title.\n var lengthOfMatchesInTitle = matchesInTitle ? matchesInTitle.join("").length : 0;\n var precisionInTitle = tiddler.title.length > 0 ? lengthOfMatchesInTitle/tiddler.title.length : 0;\n \n // calculate a weighted score\n var rank= nMatchesInTitle * matchInTitleWeight \n + nMatchesInTags * matchInTagsWeight \n + precisionInTitle * precisionInTitleWeight \n + 1;\n\n return rank;\n};\n\n// @return Tiddler[]\n//\nvar findMatches = function(store, searchText,caseSensitive,useRegExp,sortField,excludeTag) {\n lastSearchText = searchText;\n\n var candidates = store.reverseLookup("tags",excludeTag,false);\n var query = new STQ(searchText,caseSensitive, false, useRegExp); \n lastQuery = query;\n\n var results = query.getMatchingTiddlers(candidates);\n\n // Rank the results\n var rankFunction = abego.YourSearch.getRankFunction();\n for (var i = 0; i < results.length; i++) {\n var tiddler = results[i];\n var rank = rankFunction(tiddler, query);\n // Add the rank information to the tiddler.\n // This is used during the sorting, but it may also\n // be used in the result, e.g. to display some "relevance" \n // information in the result \n tiddler.searchRank = rank; \n }\n \n // sort the result, taking care of the rank and the sortField \n if(!sortField) {\n sortField = "title";\n }\n \n var sortFunction = function (a,b) {\n var searchRankDiff = a.searchRank - b.searchRank;\n if (searchRankDiff == 0) {\n if (a[sortField] == b[sortField]) {\n return(0); \n } else {\n return (a[sortField] < b[sortField]) ? -1 : +1; \n }\n } else {\n return (searchRankDiff > 0) ? -1 : +1; \n }\n };\n results.sort(sortFunction);\n \n lastResults = results;\n \n return results;\n};\n\n\n//----------------------------------------------------------------------------\n// Handling "limited marked text" in the preview\n//\n// The found/matched texts should be displayed to the user in the preview. To make \n// it more useful the matched texts should be shown in their contexts, i.e. with\n// some text around them. Since we only have limited space for the preview \n// (around two lines for the text preview, less for the tags and title) and \n// also don't want to both the user with "too much context" we use some \n// heuristics to find the "best context (size)". \n//\n// On the other hand we want to use as much as possible of the preview area, \n// so if there is room left we also display as much text from the beginning\n// of the text as possible. This gives the user some kind of "overall context"\n// especiallay if the start of the text is introductorily.\n//\n// Text Ranges\n//\n// To represent the ranges that should be displayed "Range" object are used.\n// This are objects with a "start" and "end" property. In a corresponding\n// "Ranges array" these objects are sorted by their start and no range object \n// intersects/touches any other of the array.\n//\n//----------------------------------------------------------------------------\n\nvar moveToWordBorder = function(s, offset, isStartOffset) {\n var wordBounds;\n if (isStartOffset) {\n wordBounds = getWordBounds(s, offset);\n } else {\n if (offset <= 0) return offset;\n wordBounds = getWordBounds(s, offset-1);\n }\n if (!wordBounds) return offset;\n \n if (isStartOffset) {\n if (wordBounds.start >= offset-maxMovementForWordCorrection) return wordBounds.start;\n if (wordBounds.end <= offset+maxMovementForWordCorrection) return wordBounds.end;\n } else {\n if (wordBounds.end <= offset+maxMovementForWordCorrection) return wordBounds.end;\n if (wordBounds.start >= offset-maxMovementForWordCorrection) return wordBounds.start;\n }\n return offset;\n};\n\nvar getContextRangeAround = function(s, startIndex, endIndex, matchCount, maxLen) {\n // Partition the available space into equal sized areas for each match and one \n // for the text start.\n // But the size should not go below a certain limit\n var size = Math.max(Math.floor(maxLen/(matchCount+1)), minMatchWithContextSize);\n \n // Substract the size of the range to get the size of the context.\n var contextSize = Math.max(size-(endIndex-startIndex), 0);\n // Two thirds of the context should be before the match, one third after.\n var contextEnd = Math.min(Math.floor(endIndex+contextSize/3), s.length);\n var contextStart = Math.max(contextEnd - size, 0);\n\n // If the contextStart/End is inside a word and the end of the word is\n // close move the pointers accordingly to make the text more readable.\n contextStart = moveToWordBorder(s, contextStart, true);\n contextEnd = moveToWordBorder(s, contextEnd, false);\n \n return {start: contextStart, end: contextEnd};\n};\n\n// Splits s into a sequence of "matched" and "unmatched" substrings, using the \n// matchRegExp to do the matching.\n// \n// Returns an array of objects with a "text" property containing the substring text. \n// Substrings that are "matches" also contain a boolean "isMatch" property set to true.\n// \n// @param matchRegExp [may be null] when null no matching is performed and the returned \n// array just contains one item with s as its text\n// \nvar getTextAndMatchArray = function(s, matchRegExp) {\n var result = [];\n if (matchRegExp) {\n var startIndex = 0;\n var n = s.length;\n var currentLen = 0;\n do {\n matchRegExp.lastIndex = startIndex;\n var match = matchRegExp.exec(s);\n if (match) {\n if (startIndex < match.index) {\n var t = s.substring(startIndex, match.index);\n result.push({text:t});\n }\n result.push({text:match[0], isMatch:true});\n startIndex = match.index + match[0].length;\n } else {\n result.push({text: s.substr(startIndex)});\n break;\n }\n } while (true);\n } else {\n result.push({text: s});\n }\n return result;\n};\n\n\nvar simpleCreateLimitedTextWithMarks = function(place, s, maxLen) {\n if (!lastQuery) return;\n \n var textAndMatches = getTextAndMatchArray(s, lastQuery.getMarkRegExp());\n var currentLen = 0;\n for (var i=0; i < textAndMatches.length && currentLen < maxLen; i++) {\n var t = textAndMatches[i];\n var text = t.text;\n if (t.isMatch) {\n createTiddlyElement(place,"span",null,"marked",text); \n } else {\n var remainingLen = maxLen-currentLen;\n if (remainingLen < text.length) {\n text = text.substring(0, remainingLen)+"...";\n }\n createTiddlyText(place, text);\n }\n currentLen += text.length;\n }\n};\n\n\n\nvar addRange = function(ranges, startIndex, endIndex) {\n var n = ranges.length;\n \n // When there are no ranges in ranges, just add it.\n if (n == 0) {\n ranges.push({start: startIndex, end: endIndex});\n return;\n }\n \n var i = 0;\n for (; i < n; i++) {\n var range = ranges[i];\n \n // find the first range that intersects or "touches" [startIndex, endIndex[\n if (range.start <= endIndex && startIndex <= range.end) {\n // Found.\n \n var r;\n // find the first range behind the new range that does not interfere\n var rIndex = i+1;\n for (; rIndex < n; rIndex++) {\n r = ranges[rIndex];\n if (r.start > endIndex || startIndex > range.end) {\n break;\n }\n }\n \n // Replace the ranges i to rIndex-1 with the union of the new range with these ranges.\n var unionStart = startIndex;\n var unionEnd = endIndex;\n for (var j = i; j < rIndex; j++) {\n r = ranges[j];\n unionStart = Math.min(unionStart, r.start);\n unionEnd = Math.max(unionEnd, r.end);\n }\n ranges.splice(i, rIndex-i, {start: unionStart, end: unionEnd});\n return; \n }\n \n // if we found a range R that is right of the new range there is no\n // intersection and we can insert the new range before R.\n if (range.start > endIndex) {\n break;\n }\n }\n\n // When we are here the new range does not interfere with any range in ranges and\n // i is the index of the first range right to it (or ranges.length, when the new range\n // becomes the right most range). \n\n ranges.splice(i, 0, {start: startIndex, end: endIndex});\n};\n\nvar getTotalRangesSize = function(ranges) {\n var totalRangeSize = 0;\n for (var i=0; i < ranges.length; i++) {\n var range = ranges[i];\n totalRangeSize += range.end-range.start;\n }\n return totalRangeSize;\n};\n\n// Processes the text between startIndex and endIndex of the textAndMatches\n// "writes" them (as DOM elements) at the given place, possibly as "marked" text.\n//\n// When endIndex is not the end of the full text an ellisis is appended. \n//\nvar writeTextAndMatchRange = function(place, s, textAndMatches, startIndex, endIndex) {\n var t;\n var text;\n \n // find the first text item to write\n var pos = 0;\n var i = 0;\n var offset = 0;\n for (;i < textAndMatches.length; i++) {\n t = textAndMatches[i];\n text = t.text;\n if (startIndex < pos+text.length) {\n offset = startIndex - pos;\n break;\n }\n pos += text.length;\n }\n \n var remainingLen = endIndex - startIndex;\n for (; i < textAndMatches.length && remainingLen > 0; i++) {\n t = textAndMatches[i];\n text = t.text.substr(offset);\n offset = 0;\n if (text.length > remainingLen) text = text.substr(0,remainingLen);\n \n if (t.isMatch) {\n createTiddlyElement(place,"span",null,"marked",text);\n } else {\n createTiddlyText(place, text);\n }\n remainingLen -= text.length;\n }\n \n if (endIndex < s.length) {\n createEllipsis(place);\n }\n};\n\nvar getMatchedTextCount = function(textAndMatches) {\n var result = 0;\n for (var i=0; i < textAndMatches.length; i++) {\n if (textAndMatches[i].isMatch) {\n result++;\n }\n }\n return result; \n};\n\n// Get all ranges around matched substrings with their contexts\n//\nvar getMatchedTextWithContextRanges = function(textAndMatches, s, maxLen) {\n var ranges = [];\n var matchCount = getMatchedTextCount(textAndMatches);\n var pos = 0;\n for (var i=0; i < textAndMatches.length; i++) {\n var t = textAndMatches[i];\n var text = t.text;\n if (t.isMatch) {\n var range = getContextRangeAround(s, pos, pos+text.length, matchCount, maxLen);\n addRange(ranges, range.start, range.end);\n }\n pos += text.length;\n }\n return ranges;\n};\n\nvar fillUpRanges = function(s, ranges, maxLen) {\n var remainingLen = maxLen - getTotalRangesSize(ranges);\n while (remainingLen > 0) {\n if (ranges.length == 0) {\n // No matches added yet. Make one large range.\n addRange(ranges, 0, moveToWordBorder(s, maxLen, false));\n return;\n } else {\n var range = ranges[0];\n var startIndex;\n var maxEndIndex;\n if (range.start == 0) {\n // The first range already starts at the beginning of the string.\n\n // When there is a second range fill to the next range start or to the maxLen.\n startIndex = range.end;\n if (ranges.length > 1) {\n maxEndIndex = ranges[1].start;\n } else {\n // Only one range. Add a range after that with the complete remaining len \n // (corrected to "beautify" the output)\n addRange(ranges, startIndex, moveToWordBorder(s, startIndex+remainingLen, false));\n return;\n }\n } else {\n // There is unused space between the start of the text and the first range.\n startIndex = 0;\n maxEndIndex = range.start;\n }\n var endIndex = Math.min(maxEndIndex, startIndex+remainingLen);\n addRange(ranges, startIndex, endIndex);\n remainingLen -= (endIndex-startIndex);\n }\n }\n};\n\n// Write the given ranges of s, using textAndMatches for marking portions of the text.\n//\nvar writeRanges = function(place, s, textAndMatches, ranges, maxLen) {\n if (ranges.length == 0) return;\n \n // When the first range is not at the start of the text write an ellipsis("...")\n // (Ellipses between ranges are written in the writeTextAndMatchRange method)\n if (ranges[0].start > 0) createEllipsis(place);\n\n var remainingLen = maxLen;\n for (var i = 0; i < ranges.length && remainingLen > 0; i++) {\n var range = ranges[i];\n var len = Math.min(range.end - range.start, remainingLen);\n writeTextAndMatchRange(place, s, textAndMatches, range.start, range.start+len);\n remainingLen -= len;\n }\n};\n\nvar createLimitedTextWithMarksAndContext = function(place, s, maxLen) {\n if (!lastQuery) return;\n \n if (s.length < maxLen) maxLen = s.length;\n \n var textAndMatches = getTextAndMatchArray(s, lastQuery.getMarkRegExp());\n \n var ranges = getMatchedTextWithContextRanges(textAndMatches, s, maxLen);\n \n // When the maxLen is not yet reached add more ranges \n // starting from the beginning until either maxLen or \n // the end of the string is reached.\n fillUpRanges(s, ranges, maxLen);\n\n writeRanges(place, s, textAndMatches, ranges, maxLen);\n};\n\nvar createLimitedTextWithMarks = function(place, s, maxLen) {\n// return simpleCreateLimitedTextWithMarks(place, s, maxLen);\n return createLimitedTextWithMarksAndContext(place, s, maxLen);\n};\n\n\n//----------------------------------------------------------------------------\n// The Search Result\n//----------------------------------------------------------------------------\n\nvar myStorySearch = function(text,useCaseSensitive,useRegExp)\n{\n highlightHack = new RegExp(useRegExp ? text:text.escapeRegExp(),useCaseSensitive ? "mg" : "img");\n var matches = findMatches(store, text,useCaseSensitive,useRegExp,"title","excludeSearch");\n\n firstIndexOnPage = 0;\n showResult();\n \n highlightHack = null;\n};\n\n\nvar myMacroSearchHandler = function(place,macroName,params)\n{\n var lastSearchText = "";\n var searchTimeout = null;\n var doSearch = function(txt)\n {\n if (config.options.chkUseYourSearch)\n myStorySearch(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);\n else\n story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);\n lastSearchText = txt.value;\n };\n var clickHandler = function(e)\n {\n doSearch(searchInputField);\n return false;\n };\n var keyHandler = function(e)\n {\n if (!e) var e = window.event;\n switch(e.keyCode)\n {\n case 13:\n doSearch(this);\n break;\n case 27:\n // When the result is open, close it, \n // otherwise clear the content of the input field\n if (isResultOpen()) {\n closeResult();\n } else {\n this.value = "";\n clearMessage();\n }\n break;\n }\n if (String.fromCharCode(e.keyCode) == this.accessKey || e.altKey) \n {\n reopenResultIfApplicable();\n }\n\n if(this.value.length<3 && searchTimeout) clearTimeout(searchTimeout);\n if((this.value.length > 2) && (this.value != lastSearchText))\n if (!config.options.chkUseYourSearch || config.options.chkSearchAsYouType)\n {\n if(searchTimeout)\n clearTimeout(searchTimeout);\n var txt = this;\n searchTimeout = setTimeout(function() {doSearch(txt);},500);\n }\n if (this.value.length == 0) \n {\n closeResult();\n }\n };\n\n\n var focusHandler = function(e)\n {\n this.select();\n reopenResultIfApplicable();\n };\n\n var btn = createTiddlyButton(place,this.label,this.prompt,clickHandler);\n var txt = createTiddlyElement(place,"input",null,null,null);\n if(params[0])\n txt.value = params[0];\n txt.onkeyup = keyHandler;\n txt.onfocus = focusHandler;\n txt.setAttribute("size",this.sizeTextbox);\n txt.setAttribute("accessKey",this.accessKey);\n txt.setAttribute("autocomplete","off");\n if(config.browser.isSafari)\n {\n txt.setAttribute("type","search");\n txt.setAttribute("results","5");\n }\n else\n txt.setAttribute("type","text");\n\n searchInputField = txt;\n searchButton = btn;\n};\n\nvar isResultOpen = function() {\n return resultElement != null && resultElement.parentNode == document.body;\n};\n\nvar closeResult = function() {\n if (isResultOpen()) {\n document.body.removeChild(resultElement);\n }\n};\n\n\nvar openAllFoundTiddlers = function() {\n closeResult();\n if (lastResults) {\n var titles=[];\n for(var i = 0; i<lastResults.length; i++)\n titles.push(lastResults[i].title);\n story.displayTiddlers(null,titles);\n }\n};\n\n// Refreshes the content of the result with the current search result\n// of the selected page.\n//\n// Assumes that the result is already open. \n//\nvar refreshResult = function() {\n if (!resultElement || !searchInputField) return;\n\n // Load the template for the YourSearchResult\n var html = store.getTiddlerText("YourSearchResultTemplate");\n if (!html) html = "<b>Tiddler YourSearchResultTemplate not found</b>";\n resultElement.innerHTML = html;\n\n // Ensure that the firstIndexOnPage is really a page start. \n // This may have become violated when the ItemsPerPage are changed,\n // e.g. when switching between previewText and simple mode.\n firstIndexOnPage = Math.floor(firstIndexOnPage / getItemsPerPage()) * getItemsPerPage();\n \n // Expand the template macros etc.\n applyHtmlMacros(resultElement,null);\n refreshElements(resultElement,null);\n \n // When there are items found add them to the result page (pagewise)\n if (lastResults && lastResults.length > 0) {\n // Load the template how to display the items that represent a found tiddler\n var itemHtml = store.getTiddlerText("YourSearchItemTemplate");\n if (!itemHtml) alertAndThrow("YourSearchItemTemplate not found");\n \n // Locate the node that shall contain the list of found tiddlers\n var items = document.getElementById(yourSearchResultItemsID);\n if(!items)\n items = createTiddlyElement(resultElement,"div",yourSearchResultItemsID);\n\n // Add the items of the current page\n var endIndex = Math.min(firstIndexOnPage+getItemsPerPage(), lastResults.length);\n indexInPage = -1;\n for (var i=firstIndexOnPage; i < endIndex; i++) {\n currentTiddler = lastResults[i];\n indexInPage++;\n indexInResult = i;\n\n var item = createTiddlyElement(items,"div",null, "yourSearchItem");\n item.innerHTML = itemHtml;\n applyHtmlMacros(item,null);\n refreshElements(item,null);\n }\n }\n \n // The currentTiddler must only be defined while rendering the found tiddlers\n currentTiddler = null;\n\n ensureResultIsDisplayedNicely();\n};\n\n// Makes sure the result page has a good size and position and visible\n// (may scroll the window)\n//\nvar ensureResultIsDisplayedNicely = function() {\n adjustResultPositionAndSize();\n scrollVisible();\n};\n\nvar scrollVisible = function() {\n // Scroll the window to make the result page (and the search Input field) visible.\n if (resultElement) window.scrollTo(0,ensureVisible(resultElement));\n if (searchInputField) window.scrollTo(0,ensureVisible(searchInputField));\n};\n\n// Adjusts the resultElement's size and position, relative to the search input field.\n//\nvar adjustResultPositionAndSize = function() {\n if (!searchInputField) return;\n \n var root = searchInputField;\n \n // Position the result below the root and resize it if necessary.\n var rootLeft = findPosX(root);\n var rootTop = findPosY(root);\n var rootHeight = root.offsetHeight;\n var popupLeft = rootLeft;\n var popupTop = rootTop + rootHeight;\n\n // Make sure the result is not wider than the window\n var winWidth = findWindowWidth();\n if (winWidth < resultElement.offsetWidth) {\n resultElement.style.width = (winWidth - 100)+"px";\n winWidth = findWindowWidth();\n }\n\n // Ensure that the left and right of the result are not\n // clipped by the window. Move it to the left or right, if necessary. \n var popupWidth = resultElement.offsetWidth;\n if(popupLeft + popupWidth > winWidth)\n popupLeft = winWidth - popupWidth-30;\n if (popupLeft < 0) popupLeft = 0;\n \n // Do the actual moving\n resultElement.style.left = popupLeft + "px";\n resultElement.style.top = popupTop + "px";\n resultElement.style.display = "block";\n};\n\nvar showResult = function() {\n if (!resultElement) {\n resultElement = createTiddlyElement(document.body,"div",yourSearchResultID,"yourSearchResult");\n } else if (resultElement.parentNode != document.body) {\n document.body.appendChild(resultElement);\n }\n\n refreshResult();\n};\n\nvar reopenResultIfApplicable = function() {\n if (searchInputField == null || !config.options.chkUseYourSearch) return;\n \n if ((searchInputField.value == lastSearchText) && lastSearchText && !isResultOpen()) {\n // For speedup we check re-use the previously created resultElement, if possible.\n if (resultElement && (resultElement.parentNode != document.body)) {\n document.body.appendChild(resultElement);\n ensureResultIsDisplayedNicely();\n } else {\n showResult();\n }\n }\n};\n\nvar setFirstIndexOnPage = function(index) {\n if (!lastResults || lastResults.length == 0) return;\n\n firstIndexOnPage = Math.min(Math.max(0, index), lastResults.length-1);\n refreshResult(); \n};\n\n\nvar onDocumentClick = function(e) {\n // Close the search result page when the user clicks on the document\n // (and not into the searchInputField, on the search button or in the result)\n if (e.target == searchInputField) return; \n if (e.target == searchButton) return; \n if (resultElement && isDescendantOrSelf(resultElement, e.target)) return; \n \n closeResult();\n};\n\nvar onDocumentKeyup = function(e) {\n // Close the search result page when the user presses "ESC"\n if (e.keyCode == 27) closeResult();\n};\naddEvent(document,"click",onDocumentClick);\naddEvent(document,"keyup",onDocumentKeyup);\n\n\n//----------------------------------------------------------------------------\n// Macros\n//----------------------------------------------------------------------------\n\n// ====Macro yourSearch ================================================\n\nconfig.macros.yourSearch = {\n // Standard Properties\n label: "yourSearch",\n prompt: "Gives access to the current/last YourSearch result",\n\n funcs: {},\n \n tests: {\n "true" : function() {return true;},\n "false" : function() {return false;},\n "found" : function() {return lastResults && lastResults.length > 0;},\n "previewText" : function() {return config.options.chkPreviewText;}\n }\n};\n\nconfig.macros.yourSearch.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length == 0) return;\n\n var name = params[0];\n var func = config.macros.yourSearch.funcs[name];\n if (func) func(place,macroName,params,wikifier,paramString,tiddler);\n};\n\nconfig.macros.yourSearch.funcs.itemRange = function(place) {\n if (lastResults) {\n var endIndex = Math.min(firstIndexOnPage+getItemsPerPage(), lastResults.length);\n var s = "%0 - %1".format([firstIndexOnPage+1,endIndex]);\n createTiddlyText(place, s);\n }\n};\n\nconfig.macros.yourSearch.funcs.count = function(place) {\n if (lastSearchText) {\n createTiddlyText(place, lastResults.length.toString());\n }\n};\n\nconfig.macros.yourSearch.funcs.query = function(place) {\n if (lastResults) {\n createTiddlyText(place, lastSearchText);\n }\n};\n\nconfig.macros.yourSearch.funcs.version = function(place) {\n var t = "YourSearch %0.%1.%2".format(\n [version.extensions.YourSearchPlugin.major, \n version.extensions.YourSearchPlugin.minor, \n version.extensions.YourSearchPlugin.revision]);\n var e = createTiddlyElement(place, "a");\n e.setAttribute("href", "http://tiddlywiki.abego-software.de/#YourSearchPlugin");\n e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">'+t+'<font>';\n};\n\nconfig.macros.yourSearch.funcs.copyright = function(place) {\n var e = createTiddlyElement(place, "a");\n e.setAttribute("href", "http://tiddlywiki.abego-software.de");\n e.innerHTML = '<font color="black" face="Arial, Helvetica, sans-serif">© 2005-2006 <b><font color="red">abego</font></b> Software<font>';\n};\n\n\nconfig.macros.yourSearch.funcs.linkButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params < 2) return;\n \n var tiddlyLink = params[1];\n var text = params < 3 ? tiddlyLink : params[2];\n var tooltip = params < 4 ? text : params[3];\n var accessKey = params < 5 ? null : params[4];\n \n var btn = createTiddlyButton(place,text,tooltip,closeResultAndDisplayTiddler,null,null, accessKey);\n btn.setAttribute("tiddlyLink",tiddlyLink);\n};\n\nconfig.macros.yourSearch.funcs.closeButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n var button = createTiddlyButton(place, "close", "Close the Search Results (Shortcut: ESC)", closeResult);\n};\n\nconfig.macros.yourSearch.funcs.openAllButton = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!lastResults) return;\n var n = lastResults.length;\n if (n == 0) return;\n\n var title = n == 1 ? "open tiddler" : "open all %0 tiddlers".format([n]);\n var button = createTiddlyButton(place, title, "Open all found tiddlers (Shortcut: Alt-O)", openAllFoundTiddlers);\n button.setAttribute("accessKey","O");\n};\n\nvar onNaviButtonClick = function(e) {\n if (!e) var e = window.event;\n var pageIndex = getIntAttribute(this, "page");\n setFirstIndexOnPage(pageIndex * getItemsPerPage(), 0);\n};\n\nconfig.macros.yourSearch.funcs.naviBar = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!lastResults || lastResults.length == 0) return;\n\n var button;\n var currentPageIndex = Math.floor(firstIndexOnPage / getItemsPerPage());\n var lastPageIndex = Math.floor((lastResults.length-1) / getItemsPerPage());\n if (currentPageIndex > 0) {\n button = createTiddlyButton(place, "Previous", "Go to previous page (Shortcut: Alt-'<')", onNaviButtonClick, "prev");\n button.setAttribute("page",(currentPageIndex-1).toString());\n button.setAttribute("accessKey","<");\n }\n\n for (var i = -maxPagesInNaviBar; i < maxPagesInNaviBar; i++) {\n var pageIndex = currentPageIndex+i;\n if (pageIndex < 0) continue;\n if (pageIndex > lastPageIndex) break;\n\n var pageNo = (i+currentPageIndex+1).toString();\n var buttonClass = pageIndex == currentPageIndex ? "currentPage" : "otherPage";\n button = createTiddlyButton(place, pageNo, "Go to page %0".format([pageNo]), onNaviButtonClick, buttonClass);\n button.setAttribute("page",(pageIndex).toString());\n }\n \n if (currentPageIndex < lastPageIndex) {\n button = createTiddlyButton(place, "Next", "Go to next page (Shortcut: Alt-'>')", onNaviButtonClick, "next");\n button.setAttribute("page",(currentPageIndex+1).toString());\n button.setAttribute("accessKey",">");\n }\n};\n\n\nconfig.macros.yourSearch.funcs["if"] = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length < 2) return;\n \n var testName = params[1];\n var negate = (testName == "not");\n if (negate) {\n if (params.length < 3) return;\n testName = params[2];\n }\n \n var test = config.macros.yourSearch.tests[testName];\n var showIt = false;\n try {\n if (test) {\n showIt = test(place,macroName,params,wikifier,paramString,tiddler) != negate;\n } else {\n // When no predefined test is specified try to evaluate it as a JavaScript expression.\n showIt = (!eval(testName)) == negate;\n }\n } catch (ex) {\n }\n \n if (!showIt) {\n place.style.display="none";\n }\n};\n\nvar createOptionWithRefresh = function(place, optionParams, wikifier,tiddler) {\n invokeMacro(place,"option",optionParams,wikifier,tiddler);\n // The option macro appended the component at the end of the place.\n var elem = place.lastChild;\n var oldOnClick = elem.onclick;\n elem.onclick = function(e) {\n var result = oldOnClick.apply(this, arguments);\n refreshResult();\n return result;\n };\n return elem;\n};\n\nconfig.macros.yourSearch.funcs.chkPreviewText = function(place,macroName,params,wikifier,paramString,tiddler) {\n var optionParams = params.slice(1).join(" ");\n \n var elem = createOptionWithRefresh(place, "chkPreviewText", wikifier,tiddler);\n elem.setAttribute("accessKey", "P");\n elem.title = "Show text preview of found tiddlers (Shortcut: Alt-P)"; \n return elem;\n};\n\n// ====Macro foundTiddler ================================================\n\nconfig.macros.foundTiddler = {\n // Standard Properties\n label: "foundTiddler",\n prompt: "Provides information on the tiddler currently processed on the YourSearch result page",\n \n funcs: {}\n};\n\n\nconfig.macros.foundTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n var name = params[0];\n var func = config.macros.foundTiddler.funcs[name];\n if (func) func(place,macroName,params,wikifier,paramString,tiddler);\n};\n\n// Closes the Search Result window and displays the tiddler \n// defined by the "tiddlyLink" attribute of this element\n//\nvar closeResultAndDisplayTiddler = function(e)\n{\n closeResult();\n \n var title = this.getAttribute("tiddlyLink");\n if(title) {\n var withHilite = this.getAttribute("withHilite");\n var oldHighlightHack = highlightHack;\n if (withHilite && withHilite=="true" && lastQuery) {\n highlightHack = lastQuery.getMarkRegExp();\n }\n story.displayTiddler(this,title);\n highlightHack = oldHighlightHack;\n }\n return(false);\n};\n\n// Returns the "shortcut number" of the currentTiddler. \n// I.e. When the user presses Alt-n the given tiddler is opened/display.\n//\n// @return 0-9 or -1 when no number is defined\n//\nvar getShortCutNumber = function() {\n if (!currentTiddler) return -1;\n \n if (indexInPage >= 0 && indexInPage <= 9) {\n return indexInPage < 9 ? (indexInPage+1) : 0;\n } else {\n return -1;\n }\n};\n\nconfig.macros.foundTiddler.funcs.title = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n \n var shortcutNumber = getShortCutNumber();\n var tooltip = shortcutNumber >= 0 \n ? "Open tiddler (Shortcut: Alt-%0)".format([shortcutNumber.toString()])\n : "Open tiddler";\n\n var btn = createTiddlyButton(place,null,tooltip,closeResultAndDisplayTiddler,null);\n btn.setAttribute("tiddlyLink",currentTiddler.title);\n btn.setAttribute("withHilite","true");\n \n createLimitedTextWithMarks(btn, currentTiddler.title, maxCharsInTitle);\n\n if (shortcutNumber >= 0) {\n btn.setAttribute("accessKey",shortcutNumber.toString());\n }\n};\n\nconfig.macros.foundTiddler.funcs.tags = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n\n createLimitedTextWithMarks(place, currentTiddler.getTags(), maxCharsInTags);\n};\n\nconfig.macros.foundTiddler.funcs.text = function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!currentTiddler) return;\n\n createLimitedTextWithMarks(place, removeTextDecoration(currentTiddler.text), maxCharsInText);\n};\n\n\n// Renders the "shortcut number" of the current tiddler, to indicate to the user\n// what number to "Alt-press" to open the tiddler.\n//\nconfig.macros.foundTiddler.funcs.number = function(place,macroName,params,wikifier,paramString,tiddler) {\n var numberToDisplay = getShortCutNumber();\n if (numberToDisplay >= 0) {\n var text = "%0)".format([numberToDisplay.toString()]);\n createTiddlyElement(place,"span",null,"shortcutNumber",text);\n }\n};\n\nfunction scrollToAnchor(name) {\n return false;\n}\n//----------------------------------------------------------------------------\n// Configuration Stuff\n//----------------------------------------------------------------------------\n\nif (config.options.chkUseYourSearch == undefined) config.options.chkUseYourSearch = true;\nif (config.options.chkPreviewText == undefined) config.options.chkPreviewText = true;\nif (config.options.chkSearchAsYouType == undefined) config.options.chkSearchAsYouType=true;\nif (config.options.chkSearchInTitle == undefined) config.options.chkSearchInTitle=true;\nif (config.options.chkSearchInText == undefined) config.options.chkSearchInText=true;\nif (config.options.chkSearchInTags == undefined) config.options.chkSearchInTags=true;\nif (config.options.txtItemsPerPage == undefined) config.options.txtItemsPerPage =itemsPerPageDefault;\nif (config.options.txtItemsPerPageWithPreview == undefined) config.options.txtItemsPerPageWithPreview=itemsPerPageWithPreviewDefault;\n\nconfig.shadowTiddlers.AdvancedOptions += "\sn<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]])//";\n\n//----------------------------------------------------------------------------\n// Shadow Tiddlers\n//----------------------------------------------------------------------------\n\nconfig.shadowTiddlers["YourSearch Introduction"] = \n "!About YourSearch\sn"+\n "\sn"+\n "YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!\sn"+\n "\sn"+\n "''May the '~Alt-F' be with you.''\sn"+\n "\sn"+\n "\sn"+\n "!Features\sn"+\n "* YourSearch searches for tiddlers that match your query ''as you type'' into the 'search' field. It presents a list of the ''\s"Top Ten\s"'' tiddlers in a ''popup-like window'': the ''[[YourSearch Result]]''. The tiddlers currently displayed in your TiddlyWiki are not affected.\sn"+\n "* Using ''~TiddlerRank technology'' the [[YourSearch Result]] lists the ''most interesting tiddlers first''.\sn"+\n "* Through ''Filtered Search'' and ''Boolean Search'' you can easily refining your search, like excluding words or searching for multiple words. This way less tiddlers are displayed in the [[YourSearch Result]] and you can faster scan the result for the tiddler you are looking for.\sn"+\n "* The [[YourSearch Result]] lists the found tiddlers ''page-wise'', e.g. 10 per page. Use the ''Result Page Navigation Bar'' to navigate between pages if the result does not fit on one page.\sn"+\n "* The [[YourSearch Result]] states the ''total number of found tiddlers''. This way you can quickly decide if you want to browse the result list or if you want to refine your search first to shorten the result list.\sn"+\n "* Beside the ''title of the found tiddlers'' the [[YourSearch Result]] also ''displays tags'' and ''tiddler text previews''. The ''tiddler text preview'' is an extract of the tiddler's content, showing the most interesting parts related to your query (e.g. the texts around the words you are looking for).\sn"+\n "* The words you are looking for are hilited in the titles, tags and text previews of the [[YourSearch Result]].\sn"+\n "* If you are not interested in the tiddler text previews but prefer to get longer lists of tiddlers on one result page you may ''switch of the text preview''.\sn"+\n "* If the [[YourSearch Result]] contains the tiddler you are looking for you can just ''click its title to display'' it in your TiddlyWiki. Alternatively you may also ''open all found tiddlers'' at once. \sn"+\n "* Use [[YourSearch Options]] to customize YourSearch to your needs. E.g. depending on the size of your screen you may change the number of tiddlers displayed in the [[YourSearch Result]]. In the [[YourSearch Options]] and the AdvancedOptions you may also switch off YourSearch in case you temporarily want to use the standard search.\sn"+\n "* For the most frequently actions ''access keys'' are defined so you can perform your search without using the mouse.\sn"+\n "\sn"\n ;\n\nconfig.shadowTiddlers["YourSearch Help"] = \n// "<html><a name='Top'/>"+\n// "<a href='javascript:scrollToAnchor(\s"Filtered\s");'>[Filtered Search] </a>"+\n// "<a href='#Boolean'>[Boolean Search] </a>"+\n// "<a href='#Exact'>['Exact Word' Search] </a>"+\n// "<a href='#Combined'>[Combined Search] </a>"+\n// "<a href='#Case'>[CaseSensitiveSearch and RegExpSearch] </a>"+\n// "<a href='#Access'>[Access Keys] </a>"+\n// "</html>"+\n "<<tiddler [[YourSearch Introduction]]>>"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Filtered Search<html><a name='Filtered'/></html>\sn"+\n "Using the Filtered Search you can restrict your search to certain parts of a tiddler, e.g only search the tags or only the titles.\sn"+\n "|!What you want|!What you type|!Example|\sn"+\n "|Search ''titles only''|start word with ''!''|{{{!jonny}}}|\sn"+\n "|Search ''contents only''|start word with ''%''|{{{%football}}}|\sn"+\n "|Search ''tags only''|start word with ''#''|{{{#Plugin}}}|\sn"+\n "\sn"+\n "You may use more than one filter for a word. E.g. {{{!#Plugin}}} finds tiddlers containing \s"Plugin\s" either in the title or in the tags (but does not look for \s"Plugin\s" in the content).\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Boolean Search<html><a name='Boolean'/></html>\sn"+\n "The Boolean Search is useful when searching for multiple words.\sn"+\n "|!What you want|!What you type|!Example|\sn"+\n "|''All words'' must exist|List of words|{{{jonny jeremy}}}|\sn"+\n "|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\sn"+\n "|A word ''must not exist''|Start word with ''-''|{{{-jonny}}}|\sn"+\n "\sn"+\n "''Note:'' When you specify two words, separated with a space, YourSearch finds all tiddlers that contain both words, but not necessarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need to put the words into quotes. I.e. you type: {{{\s"john brown\s"}}}.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!'Exact Word' Search<html><a name='Exact'/></html>\sn"+\n "By default a search result all matches that 'contain' the searched text. \sn"+\n " E.g. if you search for 'Task' you will get all tiddlers containing 'Task', but also 'CompletedTask', 'TaskForce' etc.\sn"+\n "\sn"+\n "If you only want to get the tiddlers that contain 'exactly the word' you need to prefix it with a '='. E.g. typing '=Task' will the tiddlers that contain the word 'Task', ignoring words that just contain 'Task' as a substring.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Combined Search<html><a name='Combined'/></html>\sn"+\n "You are free to combine the various search options. \sn"+\n "\sn"+\n "''Examples''\sn"+\n "|!What you type|!Result|\sn"+\n "|{{{!jonny !jeremy -%football}}}| all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its titles, but no {{{football}}} in content.|\sn"+\n "|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact word). Tags named 'CompletedTask', 'TaskForce' etc. are not considered.|\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!~CaseSensitiveSearch and ~RegExpSearch<html><a name='Case'/></html>\sn"+\n "The standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearch. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"+\n "!Access Keys<html><a name='Access'/></html>\sn"+\n "You are encouraged to use the access keys (also called \s"shortcut\s" keys) for the most frequently used operations. For quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\sn"+\n "\sn"+\n "|!Key|!Operation|\sn"+\n "|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search input field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the previous search result. This way you can quickly display multiple tiddlers using \s"Press {{{Alt-F}}}. Select tiddler.\s" sequences.|\sn"+\n "|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Result]] is already closed and the cursor is in the search input field the field's content is cleared so you start a new query.|\sn"+\n "|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second etc. tiddler from the result list.|\sn"+\n "|{{{Alt-O}}}|Opens all found tiddlers.|\sn"+\n "|{{{Alt-P}}}|Toggles the 'Preview Text' mode.|\sn"+\n "|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[YourSearch Result]].|\sn"+\n "|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the {{{Return}}} key actually starts the search (as does pressing the 'search' button).|\sn"+\n// "<html><sub><a href='#Top'>[Top]</a></sub></html>\sn"+\n "\sn"\n ;\n\nconfig.shadowTiddlers["YourSearch Options"] = \n "|>|!YourSearch Options|\sn"+\n "|>|<<option chkUseYourSearch>> Use 'Your Search'|\sn"+\n "|!|<<option chkPreviewText>> Show Text Preview|\sn"+\n "|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required to start search)|\sn"+\n "|!|Default Search Filter:<<option chkSearchInTitle>>Titles ('!') <<option chkSearchInText>>Texts ('%') <<option chkSearchInTags>>Tags ('#') <html><br><font size=\s"-2\s">The parts of a tiddlers that are searched when you don't explicitly specify a filter in the search text (using a '!', '%' or '#' prefix).</font></html>|\sn"+\n "|!|Number of items on search result page: <<option txtItemsPerPage>>|\sn"+\n "|!|Number of items on search result page with preview text: <<option txtItemsPerPageWithPreview>>|\sn"\n ;\n \nconfig.shadowTiddlers["YourSearchStyleSheet"] = \n "/***\sn"+\n "!~YourSearchResult Stylesheet\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult {\sn"+\n "\stposition: absolute;\sn"+\n "\stwidth: 800px;\sn"+\n "\sn"+\n "\stpadding: 0.2em;\sn"+\n "\stlist-style: none;\sn"+\n "\stmargin: 0;\sn"+\n "\sn"+\n "\stbackground: White;\sn"+\n "\stborder: 1px solid DarkGray;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Summary Section\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult .summary {\sn"+\n "\stborder-bottom-width: thin;\sn"+\n "\stborder-bottom-style: solid;\sn"+\n "\stborder-bottom-color: #999999;\sn"+\n "\stpadding-bottom: 4px;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchRange, .yourSearchCount, .yourSearchQuery {\sn"+\n "\stfont-weight: bold;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchResult .summary .button {\sn"+\n "\stfont-size: 10px;\sn"+\n "\sn"+\n "\stpadding-left: 0.3em;\sn"+\n "\stpadding-right: 0.3em;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchResult .summary .chkBoxLabel {\sn"+\n "\stfont-size: 10px;\sn"+\n "\sn"+\n "\stpadding-right: 0.3em;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Items Area\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchResult .marked {\sn"+\n "\stbackground: none;\sn"+\n "\stfont-weight: bold;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchItem {\sn"+\n "\stmargin-top: 2px;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNumber {\sn"+\n "\stcolor: #808080;\sn"+\n "}\sn"+\n "\sn"+\n "\sn"+\n ".yourSearchTags {\sn"+\n "\stcolor: #008000;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchText {\sn"+\n "\stcolor: #808080;\sn"+\n "\stmargin-bottom: 6px;\sn"+\n "}\sn"+\n "\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Footer\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchFooter {\sn"+\n "\stmargin-top: 8px;\sn"+\n "\stborder-top-width: thin;\sn"+\n "\stborder-top-style: solid;\sn"+\n "\stborder-top-color: #999999;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchFooter a:hover{\sn"+\n "\stbackground: none;\sn"+\n "\stcolor: none;\sn"+\n "}\sn"+\n "/*}}}*/\sn"+\n "/***\sn"+\n "!!Navigation Bar\sn"+\n "***/\sn"+\n "/*{{{*/\sn"+\n ".yourSearchNaviBar a {\sn"+\n "\stfont-size: 16px;\sn"+\n "\stmargin-left: 4px;\sn"+\n "\stmargin-right: 4px;\sn"+\n "\stcolor: black;\sn"+\n "\sttext-decoration: underline;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar a:hover {\sn"+\n "\stbackground-color: none;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .prev {\sn"+\n "\stfont-weight: bold;\sn"+\n "\stcolor: blue;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .currentPage {\sn"+\n "\stcolor: #FF0000;\sn"+\n "\stfont-weight: bold;\sn"+\n "\sttext-decoration: none;\sn"+\n "}\sn"+\n "\sn"+\n ".yourSearchNaviBar .next {\sn"+\n "\stfont-weight: bold;\sn"+\n "\stcolor: blue;\sn"+\n "}\sn"+\n "/*}}}*/\sn"\n ;\n\nconfig.shadowTiddlers["YourSearchResultTemplate"] = \n "<!--\sn"+\n "{{{\sn"+\n "-->\sn"+\n "<span macro=\s"yourSearch if found\s">\sn"+\n "<!-- The Summary Header ============================================ -->\sn"+\n "<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stYourSearch Result <span class=\s"yourSearchRange\s" macro=\s"yourSearch itemRange\s"></span>\sn"+\n "\st\st of <span class=\s"yourSearchCount\s" macro=\s"yourSearch count\s"></span>\sn"+\n "\st\stfor <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>\sn"+\n "\st</td>\sn"+\n "\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+\n "\st\st<span macro=\s"yourSearch chkPreviewText\s"></span><span class=\s"chkBoxLabel\s">preview text</span>\sn"+\n "\st\st<span macro=\s"yourSearch openAllButton\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "\sn"+\n "<!-- The List of Found Tiddlers ============================================ -->\sn"+\n "<div id=\s"yourSearchResultItems\s" itemsPerPage=\s"25\s" itemsPerPageWithPreview=\s"10\s"></div>\sn"+\n "\sn"+\n "<!-- The Footer (with the Navigation) ============================================ -->\sn"+\n "<table class=\s"yourSearchFooter\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stResult page: <span class=\s"yourSearchNaviBar\s" macro=\s"yourSearch naviBar\s"></span>\sn"+\n "\st</td>\sn"+\n "\st<td align=\s"right\s"><span macro=\s"yourSearch version\s"></span>, <span macro=\s"yourSearch copyright\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "<!-- end of the 'tiddlers found' case =========================================== -->\sn"+\n "</span>\sn"+\n "\sn"+\n "\sn"+\n "<!-- The \s"No tiddlers found\s" case =========================================== -->\sn"+\n "<span macro=\s"yourSearch if not found\s">\sn"+\n "<table class=\s"summary\s" border=\s"0\s" width=\s"100%\s" cellspacing=\s"0\s" cellpadding=\s"0\s"><tbody>\sn"+\n " <tr>\sn"+\n "\st<td align=\s"left\s">\sn"+\n "\st\stYourSearch Result: No tiddlers found for <span class=\s"yourSearchQuery\s" macro=\s"yourSearch query\s"></span>.\sn"+\n "\st</td>\sn"+\n "\st<td class=\s"yourSearchButtons\s" align=\s"right\s">\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Options' options 'Configure YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch linkButton 'YourSearch Help' help 'Get help how to use YourSearch'\s"></span>\sn"+\n "\st\st<span macro=\s"yourSearch closeButton\s"></span>\sn"+\n "\st</td>\sn"+\n " </tr>\sn"+\n "</tbody></table>\sn"+\n "</span>\sn"+\n "\sn"+\n "\sn"+\n "<!--\sn"+\n "}}}\sn"+\n "-->\sn"\n ;\n\nconfig.shadowTiddlers["YourSearchItemTemplate"] = \n "<!--\sn"+\n "{{{\sn"+\n "-->\sn"+\n "<span class='yourSearchNumber' macro='foundTiddler number'></span>\sn"+\n "<span class='yourSearchTitle' macro='foundTiddler title'/></span> - \sn"+\n "<span class='yourSearchTags' macro='foundTiddler tags'/></span>\sn"+\n "<span macro=\s"yourSearch if previewText\s"><div class='yourSearchText' macro='foundTiddler text'/></div></span>\sn"+\n "<!--\sn"+\n "}}}\sn"+\n "-->"\n ;\nconfig.shadowTiddlers["YourSearch"] = "<<tiddler [[YourSearch Help]]>>";\n\nconfig.shadowTiddlers["YourSearch Result"] = "The popup-like window displaying the result of a YourSearch query.";\n\n\nsetStylesheet(\n store.getTiddlerText("YourSearchStyleSheet"),\n "yourSearch");\n\n//----------------------------------------------------------------------------\n// Install YourSearch\n//----------------------------------------------------------------------------\n\n// Overwrite the TiddlyWiki search handler and verify after a while \n// that nobody else has overwritten it.\n\nvar origMacros_search_handler = config.macros.search.handler;\nconfig.macros.search.handler = myMacroSearchHandler;\n\n\nvar ownsOverwrittenFunctions = function() {\n var result = (config.macros.search.handler == myMacroSearchHandler);\n return result;\n};\n\nvar checkForOtherHijacker = function() {\n if (!ownsOverwrittenFunctions()) {\n alert("Message from YourSearchPlugin:\sn\sn\sn"+\n "Another plugin has disabled the 'Your Search' features.\sn\sn\sn"+\n "You may disable the other plugin or change the load order of \sn"+\n "the plugins (by changing the names of the tiddlers)\sn"+ \n "to enable the 'Your Search' features.");\n }\n};\n\nsetTimeout(checkForOtherHijacker, 5000);\n\n\n// === Public API =================================\n\nabego.YourSearch.getStandardRankFunction = function() {\n return standardRankFunction;\n};\n\nabego.YourSearch.getRankFunction = function() {\n return abego.YourSearch.getStandardRankFunction();\n};\n\nabego.YourSearch.getCurrentTiddler = function() {\n return currentTiddler;\n};\n\n} // of "install only once"\n//}}}\n// Used Globals (for JSLint) ==============\n\n// ... JavaScript Core\n/*global alert,clearTimeout,confirm */\n// ... TiddlyWiki Core\n/*global Tiddler, applyHtmlMacros, clearMessage, createTiddlyElement, createTiddlyButton, createTiddlyText, ensureVisible ,findPosX, highlightHack, findPosY,findWindowWidth, invokeMacro, saveChanges, refreshElements, story */\n\n/***\n%/\n!Licence and Copyright\nCopyright (c) abego Software ~GmbH, 2005-2006 ([[www.abego-software.de|http://www.abego-software.de]])\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\nNeither the name of abego Software nor the names of its contributors may be\nused to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n***/\n\n
<html><iframe src=http://localhost:10080/ width=100% height=600><iframe></html>
In my LAN I have a server in which all the /home for users reside. The /home \nis shared via NFS. The server also as a NIS server. The server is running \nCentos 4.1.\n\nOther machines (including my desktop) in the LAN mount the /home from the \nserver, using automount. \n\nHere is /etc/auto.master:\n{{{\n/home /etc/auto.home\n}}}\nand /etc/auto.home:\n{{{\n* -rw,intr,soft,timeo=300,tcp,rsize=32768,wsize=32768 server1:/home/&\n}}}
Tags the tiddlers that belong to the "basic set" of tiddlers, i.e. those tiddlers that are necessary to have a consistent TiddlyWiki. \n\nIt is a little bit more than the "empty.html" TiddlyWiki in that it tries to avoid unresolved links.\n\nThe "basic" tiddlers form the framework other stuff (like plugins, documentation, examples etc.) are included in. \n\nWhen publishing a TiddlyWiki the "basic" tiddlers must always be included.
from [[the jackol's den|http://www.thejackol.com/htaccess-cheatsheet/]]\nHere is a simple cheatsheet for the .htaccess file:\n\nEnable Directory Browsing\n{{{\nOptions +Indexes\n## block a few types of files from showing\nIndexIgnore *.wmv *.mp4 *.avi\n}}}\nDisable Directory Browsing\n{{{\nOptions All -Indexes\nCustomize Error Messages\nErrorDocument 403 /forbidden.html\nErrorDocument 404 /notfound.html\nErrorDocument 500 /servererror.html\n}}}\nGet SSI working with HTML/SHTML\n{{{\nAddType text/html .html\nAddType text/html .shtml\nAddHandler server-parsed .html\nAddHandler server-parsed .shtml\n# AddHandler server-parsed .htm\n}}}\nChange Default Page (order is followed!)\n{{{\nDirectoryIndex myhome.htm index.htm index.php\n}}}\nBlock Users from accessing the site\n{{{\n<limit GET POST PUT>\norder deny,allow\ndeny from 202.54.122.33\ndeny from 8.70.44.53\ndeny from .spammers.com\nallow from all\n</limit>\n}}}\nAllow only LAN users\n{{{\norder deny,allow\ndeny from all\nallow from 192.168.0.0/24\n}}}\nRedirect Visitors to New Page/Directory\n{{{\nRedirect oldpage.html http://www.domainname.com/newpage.html\nRedirect /olddir http://www.domainname.com/newdir/\n}}}\nBlock site from specific referrers\n{{{\nRewriteEngine on\nRewriteCond %{HTTP_REFERER} site-to-block\s.com [NC]\nRewriteCond %{HTTP_REFERER} site-to-block-2\s.com [NC]\nRewriteRule .* - [F]\n}}}\nBlock Hot Linking/Bandwidth hogging\n{{{\nRewriteEngine on\nRewriteCond %{HTTP_REFERER} !^$\nRewriteCond %{HTTP_REFERER} !^http://(www\s.)?mydomain.com/.*$ [NC]\nRewriteRule \s.(gif|jpg)$ - [F]\n}}}\nWant to show a ?Stealing is Bad? message too?\nAdd this below the Hot Link Blocking code:\n{{{\nRewriteRule \s.(gif|jpg)$ http://www.mydomain.com/dontsteal.gif [R,L]\n}}}\nStop .htaccess (or any other file) from being viewed\n{{{\n<files file-name>\norder allow,deny\ndeny from all\n</files>\n}}}\nAvoid the 500 Error\n{{{\n# Avoid 500 error by passing charset\nAddDefaultCharset utf-8\n}}}\nGrant CGI Access in a directory\n{{{\nOptions +ExecCGI\nAddHandler cgi-script cgi pl\n# To enable all scripts in a directory use the following\n# SetHandler cgi-script\n}}}\nPassword Protecting Directories\nUse the .htaccess Password Generator and follow the brief instructions!\n\nChange Script Extensions\n{{{\nAddType application/x-httpd-php .gne\n}}}\ngne will now be treated as PHP files! Similarly, x-httpd-cgi for CGI files, etc.\n\nUse MD5 Digests\nPerformance may take a hit but if thats not a problem, this is a nice option to turn on.\n{{{\nContentDigest On\n}}}\nThe CheckSpelling Directive\nFrom Jens Meiert: CheckSpelling corrects simple spelling errors (for example, if someone forgets a letter or if any character is just wrong). Just add CheckSpelling On to your htaccess file.\n\nThe ContentDigest Directive\nAs the Apache core features documentation says: ?This directive enables the generation of Content-MD5 headers as defined in RFC1864 respectively RFC2068. The Content-MD5 header provides an end-to-end message integrity check (MIC) of the entity-body. A proxy or client may check this header for detecting accidental modification of the entity-body in transit.\nNote that this can cause performance problems on your server since the message digest is computed on every request (the values are not cached). Content-MD5 is only sent for documents served by the core, and not by any module. For example, SSI documents, output from CGI scripts, and byte range responses do not have this header.?\nTo turn this on, just add ContentDigest On.\n\nSave Bandwidth\n{{{\n# Only if you use PHP\n<ifmodule mod_php4.c>\nphp_value zlib.output_compression 16386\n</ifmodule>\n}}}\nTurn off magic_quotes_gpc\n{{{\n# Only if you use PHP\n<ifmodule mod_php4.c>\nphp_flag magic_quotes_gpc off\n</ifmodule>\n}}}
''Syntax'' \n|[''in'' //tiddlyWikiPath//]|\n\nThe //tiddlyWikiPath// in the [[ForEachTiddlerMacro]]s inClause is a path to a TiddlyWiki file. The [[ForEachTiddlerMacro]] will use the tiddlers of that TiddlyWiki.\n \nWhen no inClause is specified the tiddlers of the current TiddlyWiki are used.\n\nExample: \n{{{\n<<forEachTiddler in 'file:///c:/SampleTiddlyWiki.html' ...\n}}}\n\nSee also [[ForEachTiddlerExamples]].
!DAAP(iTunes) share location from the command line\nThis can be checked by running on OSX: \n{{{mDNS -B _daap._tcp}}}\nor on Linux \n{{{mDNSBrowse _daap._tcp}}}\nThis way, you'll see whenever something announces itself as being daap.
You must modify your name service switch look up file to enable\nmulticast DNS lookups. If you wish to resolve only IPv6 addresses\nuse mdns6. For IPv4 addresses only, use mdns4. To resolve both\nuse mdns. Keep in mind that mdns will be slower if there are no\nIPv6 addresses published via mDNS on the network. There are also\nminimal (mdns?_minimal) libraries which only lookup .local hosts\nand 169.254.x.x addresses.\n\nAdd the appropriate mdns into the hosts line in /etc/nsswitch.conf\nAn example line looks like:\n{{{\nhosts: files mdns4_minimal [NOTFOUND=return] dns mdns4\n}}}\nIf you want to perform mDNS lookups for domains other than the ones\nending in .local, add them to /etc/mdns.allow\n
http://pasky.or.cz/~pasky/dev/retty/
''Syntax'' \n|[''script'' //scriptText//]|\n\nThe //scriptText// in the [[ForEachTiddlerMacro]]s scriptClause is a JavaScript text. It typically defines JavaScript "helper" functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...). It main purpose is to make the expressions more simpler and to allow reuse of code.\n\nSee also [[ForEachTiddlerExamples]].
''Syntax''\n|[''sortBy'' //sortExpression// [''ascending'' or ''descending'']]|\n\nUsing the sortClause of the [[ForEachTiddlerMacro]] you can specify the order the tiddlers are processed. \n\nThe sortClause consists of the sortExpression and the sort order directive (''ascending'' or ''descending'').\n\nThe sortExpression is a (quoted) JavaScript expression returning the value that should be used for sorting. The value is anything that can be compared using {{{<}}}, {{{>}}} and {{{==}}}. In the sortExpression you refer to the build-in variable {{{tiddler}}} to access the "current" tiddler. \n\nA typical sortExpression is {{{'tiddler.title'}}} to sort by title or {{{'tiddler.modified'}}} to sort by modification time. But you are not limited to only access the tiddlers properties, you may to more complex stuff like {{{'tiddler.title.length'}}}: this will sort the tiddlers by the length of their titles.\n\nWith the sort order directives ''ascending'' and ''descending'' you specify if the smaller one should be processed before the larger ones (''ascending'') or vice versa (''descending''). When no sort order directive is given ''ascending'' is used.\n\nSee also [[ForEachTiddlerExamples]].
#!/usr/bin/ruby\n# store.cgi - store command\n# version : 1.1.3 - 2006/11/1 - BidiX@BidiX.info\n# Copyright (c) BidiX@BidiX.info 2006\n#\n# this file provides the full UploadService as a single ruby cgi file\n# CONFIGs must be adjust, especially Users. \n# \n# Comments and suggestions are welcome.\n#---------------------------------------\n#$LOAD_PATH\n$: << '../lib'\n# require 'config'\n# config.rb could be a separate file\n#---------------------------------------\n#\n# config.rb - configuration du site\n# version : 1.0.0 - 02/08/2006 - BidiX@BidiX.info\n# Copyright (c) BidiX@BidiX.info 2006\n\nCONFIG = {\n :users => {\n 'UserName1'=>'Password1',\n 'UserName2'=>'Password2',\n 'UserName3'=>'Password3'\n },\n :authenticateUser => true,\n :backupExistingFile => true,\n :withUploadDir => true,\n :checkLock => true,\n :permittedFileNames => false # %w[index.html index.xml], # false means any filename\n}\n#---------------------------------------\n# require 'lock' \n# lock.rb could be a separate file\n#---------------------------------------\n#\n\nLOCK_CONFIG = {\n :defaultFile => 'index.html',\n :lockSuffix => '.lock'\n}\n\nrequire 'cgi'\n\nclass Lock\n attr_reader :username, :mtime, :locktime\n def initialize(file, lockSuffix)\n @file = file\n @lockfile = @file + lockSuffix\n @username = ''\n @mtime = 0\n @locktime = 0\n begin\n @mtime = File.new(@file).mtime.to_i\n rescue\n @mtime = 0\n end\n _readLockfile\n end\n \n def _readLockfile\n @username = ''\n @locktime = 0\n if File.exists?(@lockfile)\n line = ''\n File.open(@lockfile, 'r') do |f|\n @locktime = f.mtime.to_i\n line = f.read()\n end\n @username = line.split(':')[0]\n end\n end\n \n def isLock?()\n ! (@username == '')\n end\n \n def lock(username)\n File.open(@lockfile, 'w') do |f|\n f.write("#{username}:#{@mtime}")\n end\n @username = username\n @locktime = File.new(@lockfile).mtime.to_i\n end \n\n def unlock()\n File.delete(@lockfile)\n @username = ''\n @locktime = 0\n end\n\n def status()\n @username\n end\n\n def _display()\n @username+':'+@mtime.to_s+":"+@locktime.to_s\n end \n \nend\n\nclass Locker < CGI\n \n def initialize(siteConfig)\n super\n file = @params['file'].first || LOCK_CONFIG[:defaultFile]\n @username = @params['username'].first\n @uploadUsername = @params['uploadUsername'].first\n @uploadPassword = @params['uploadPassword'].first\n @action = @params['action'].first || 'status'\n @lock = Lock.new(file, LOCK_CONFIG[:lockSuffix])\n @siteConfig = siteConfig # for siteConfig[:users][@uploadUsername] == \n end\n \n def authenticateUser() \n if @siteConfig[:users][@uploadUsername] != @uploadPassword\n out() {"Error : Username or Password do not match \snUser: #{@uploadUsername} Password: #{@uploadPassword}"}\n return false\n else \n return true\n end\n end\n\n def display()\n if @lock.isLock?\n "File locked by: #{@lock.username}<br>\sn\s\n File modified at: #{Time.at(@lock.mtime.to_i)} (#{@lock.mtime})<br>\sn\s\n File locked at: #{Time.at(@lock.locktime.to_i)} (#{@lock.locktime})"\n else\n "Not locked"\n end\n end\n\n def respond\n begin\n case @action \n \n when 'lock'\n if authenticateUser\n if @lock.isLock? \n out() {"This file is already locked by #{@lock.status}.<br>status:#{@lock.status}"}\n elsif @lock.mtime.to_s != @params['mtime'].first\n out() {"This file has changed since you accessed it. You can't lock it."}\n else\n @lock.lock(@username)\n out() {"File locked. Now, only #{@lock.status} can upload it.<br>lock:#{@lock._display}<br>status:#{@lock.status}"}\n end\n end\n when 'display'\n out() {"#{display}"}\n \n when 'status'\n if @lock.isLock?\n out() {"This file is locked by #{@lock.status}.<br>status:#{@lock.status}"}\n else\n out() {"This file is not locked.<br>status:"}\n end\n \n when 'unlock'\n if authenticateUser\n if ! @lock.isLock?\n out() {"This file is not locked.<br>status:"}\n else\n if (@lock.username == @params['username'].first) && (@lock.mtime.to_s == @params['mtime'].first) && (@lock.locktime.to_s == @params['locktime'].first)\n @lock.unlock()\n out() {"This file is now unlocked.<br>status:"}\n else\n out() {"You are not allowed to unlock the file.<br>status:#{@lock.status}"}\n end\n end\n end\n \n when 'forceUnlock'\n if authenticateUser\n if ! @lock.isLock?\n out() {"This file is not locked.<br>status:"}\n else\n @lock.unlock()\n out() {"This file is now unlocked.<br>status:"}\n end\n end \n # when 'help'\n # outputPage\n else\n out() {"action #{@params['action'].first} not found"}\n end\n rescue Exception => e\n out() {"Error in lock : " + e}\n end\n end\nend\n\n#---------------------------------------\n# require 'storer' \n# storer.rb could be a separate file\n#---------------------------------------\n#\n# storer.rb - store a file on a webserver\n# version : 1.1.3 - 2006/10/30- BidiX@BidiX.info\n# \n# see : \n# http://tiddlywiki.bidi.info/#UploadPlugin for details on uploading files\n# usage : \n# POST \n# UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;[lockuser=<lockUser>;mtime=<mtime>;locktime=<locktime>]]\n# userfile <file>\n# GET\n# \n# Revision history\n\n# V 1.1.3 - 2006/10/30 :\n# control of empty uploaded file\n# saveFile function that can be overwritten (SimonBaird's request)\n# V 1.1.2 - 02/09/2006 :\n# return mtime, destfile and backupfile after the message line\n# v 1.1.1 - 17/08/2006 :\n# Merge avec DownloadService\n# v 1.1.0 - 28/06/2006 :\n# lock control\n# v 1.0.3 - 08/08/2006 :\n# no backup file if backupDir option is empty\n# V 1.0.2 - 15/08/2006 (DownloadService) :\n# substitue javascript included by download.cgi by filename\n# v 1.0.2 tiddlyspot - 28/06/2006 :\n# added DEFAULT_CONFIG (SimonBaird)\n# V 1.0.1 - 27/06/2006 : \n# improvements by SimonBaird\n# :permittedFileNames\n# rescue clause improvement\n# v 1.0.0 - 26/06/2006 : \n# version compatible with UploadPlugin V 3.3.2\n#\n# Copyright (c) BidiX@BidiX.info 2006\n\n# adjust defaults as required\nDEFAULT_CONFIG = {\n :users => {},\n :authenticateUser => true,\n :backupExistingFile => true,\n :withUploadDir => true,\n :checkLock => true,\n :permittedFileNames => %w[index.html index.xml], # false means any file\n}\n\nrequire 'cgi'\nrequire 'fileutils'\nrequire 'date'\nrequire 'lock'\n\n\nclass Storer < CGI\n \n Storer::PAGE = \n <<-EOP\n <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> \n <html>\n <head>\n <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >\n <title>BidiX.info - TiddlyWiki UploadService - Store script</title>\n </head>\n <body>\n <p>\n <p>store.cgi V 1.1.3\n <p>BidiX@BidiX.info\n <p> </p>\n <p> </p>\n <p> </p>\n <p align="center">This page is designed to upload a <a href="http://www.tiddlywiki.com/">TiddlyWiki<a>.</p>\n <p align="center">for details see : <a href="http://tiddlywiki.bidix.info/#HowToUpload">TiddlyWiki.BidiX.info/#HowToUpload<a>.</p> \n </body>\n </html>\n EOP\n \n def backup()\n @userfile.original_filename.sub(/([^\s.]+).(.*)/, ' ')\n @backupfile = @options['backupDir']+$1+DateTime.now.strftime('.%Y%m%d.%H%M%S0000.')+$2\n FileUtils.mv(@destfile, @backupfile)\n end\n \n def getOptions()\n @userfile = params['userfile'].first \n @destfile = @userfile.original_filename\n uploadOptions = params['UploadPlugin'].first\n @options = {}\n if uploadOptions \n uploadOptions.read.split(';').each do |element| \n (key,value) = element.split('=') \n @options[key] = value\n end\n end\n # puts "Content-Type: text/plain\sn\sn"\n # @options.each_key { |key| puts("#{key}=#{@options[key]}") }\n # @config.each_key { |key| puts("#{key}=#{@config[key]}") }\n # @config[:users].each_key { |key| puts("#{key}=#{@config[:users][key]}") }\n end\n\n def initialize(config)\n super('')\n @config = DEFAULT_CONFIG\n @config.update(config)\n end\n \n def mkDir(dirType)\n if dir = @options[dirType]\n FileUtils.mkdir_p(dir, :mode => 0755)\n if dir.rindex('/') != dir.length-1 # dir end with / \n @options[dirType] += '/'\n end\n else\n @options[dirType] = './'\n end\n end\n\n def outputPage()\n out() {Storer::PAGE}\n end\n \n def respond()\n if (request_method == 'POST')\n getOptions()\n # Autenticate User ?\n if @config[:authenticateUser] && ! (@options['user'] && @options['password'] && (@config[:users][@options['user']] == @options['password']))\n #out() {"Error : Username or Password do not match \snUser: #{@options['user']} Password: #{@options['password']}"}\n out() {"Error : Username or Password do not match \snUser: #{@options['user']}"}\n return\n end\n # File permitted ?\n if @config[:permittedFileNames] && !@config[:permittedFileNames].include?(@destfile)\n raise "filename '#{@destfile}' not permitted" \n end\n # File locked ?\n lock = false\n if @config[:checkLock]\n # Check the lock\n lock = Lock.new(@destfile, '.lock')\n if lock.isLock? && !((@options['lockuser'] == lock.username) && (@options['mtime'] == lock.mtime.to_s) && (@options['locktime'] == lock.locktime.to_s))\n out() {"You are not allowed to upload. The file #{@destfile} is locked by #{lock.username}.\sn"}\n return\n end\n end\n store()\n if lock && lock.isLock?\n lock.unlock\n end\n else\n outputPage()\n end\n end \n \n # recursively replace:\n # <!--DOWNLOAD-INSERT-FILE: "aFile.js"--><script type="text/javascript">aFile.js content</script>\n # with:\n # <script type="text/javascript" src="aFile.js"></script>\n\n def recursiveReplaceJS(content)\n #if content =~ /<!--DOWNLOAD-INSERT-FILE:\s"(.*)\s"--><script\ss+type=\s"text\s/javascript\s">\sn.*\sn<\s/script>/\n if content =~ /<!--DOWNLOAD-INSERT-FILE:\s"([^"]*)\s"--><script\ss+type=\s"text\s/javascript\s">.*?<\s/script>/m\n contentTail = recursiveReplaceJS($')\n #out() {"Found #{$&}"}\n content = $` + "<script type=\s"text/javascript\s" src=\s"#{$1}\s"></script>" + contentTail\n end\n return content\n end\n \n def saveFile(content)\n f = File.open(@destfile,'w')\n f.write(content)\n mtime = f.mtime.to_i\n f.close\n return mtime\n end\n \n \n def store()\n begin\n if @config[:withUploadDir] \n mkDir('uploaddir') \n @destfile = @options['uploaddir'] + @destfile\n end\n if @config[:backupExistingFile] && @options['backupDir']\n mkDir('backupDir')\n if File.exists?(@destfile)\n backup()\n end\n end\n saveThisContent = @userfile.read\n if (!saveThisContent)\n raise "Null content"\n end\n if ( saveThisContent.length == 0)\n raise "Zero length content"\n end\n saveThisContent = recursiveReplaceJS(saveThisContent)\n mtime = saveFile(saveThisContent)\n backupMsg = if @backupfile then "backupfile:#{@backupfile}\sn" else '' end\n out() {"0 - File successfully loaded in #{@destfile}\sndestfile:#{@destfile.sub(/^.\s//,'')}\sn#{backupMsg}mtime:#{mtime}"}\n rescue Exception => e\n out() {"Error in UploadService-storer.rb : " + e}\n end\n end\nend\n#---------------------------------------\n\nstorer = Storer.new(CONFIG)\nstorer.respond\n
<?php\n/***\n! User settings\nEdit these lines according to your need\n***/\n//{{{\n$AUTHENTICATE_USER = true; // true | false\n$USERS = array(\n 'UserName1'=>'Password1', \n 'UserName2'=>'Password2', \n 'UserName3'=>'Password3'); // set usernames and strong passwords\n$DEBUG = false; // true | false\nerror_reporting(E_ERROR | E_WARNING | E_PARSE);\n//}}}\n/***\n!Code\nNo change needed under\n***/\n//{{{\n\n/***\n * store.php - upload a file in this directory\n * version :1.4.3 - 2006/10/17 - BidiX@BidiX.info\n * \n * see : \n * http://tiddlywiki.bidi.info/#UploadPlugin for usage\n * http://www.php.net/manual/en/features.file-upload.php \n * for détails on uploading files\n * usage : \n * POST \n * UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;uploadir=<uploaddir>]\n * userfile <file>\n * GET\n *\n * Revision history\n * V 1.4.3 - 2006/10/17 \n * Test if $filename.lock exists for GroupAuthoring compatibility\n * return mtime, destfile and backupfile after the message line\n * V 1.4.2 - 2006/10/12\n * add error_reporting(E_PARSE);\n * v 1.4.1 - 15/03/2006\n * add chmo 0664 on the uploadedFile\n * v 1.4 - 23/02/2006 :\n * add uploaddir option : a path for the uploaded file relative to the current directory\n * backupdir is a relative path\n * make recusively directories if necessary for backupDir and uploadDir\n * v 1.3 - 17/02/2006 :\n * presence and value of user are checked with $USERS Array (thanks to PauloSoares)\n * v 1.2 - 12/02/2006 : \n * POST \n * UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;]\n * userfile <file>\n* if $AUTHENTICATE_USER\n * presence and value of user and password are checked with \n * $USER and $PASSWORD\n * v 1.1 - 23/12/2005 : \n * POST UploadPlugin[backupDir=<backupdir>] userfile <file>\n * v 1.0 - 12/12/2005 : \n * POST userfile <file>\n *\n * Copyright (c) BidiX@BidiX.info 2005-2006\n ***/\n//}}}\n\n//{{{\n\nif ($_SERVER['REQUEST_METHOD'] == 'GET') {\n /*\n * GET Request\n */\n ?>\n <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n <html>\n <head>\n <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >\n <title>BidiX.info - TiddlyWiki UploadPlugin - Store script</title>\n </head>\n <body>\n <p>\n <p>store.php V 1.4.3\n <p>BidiX@BidiX.info\n <p> </p>\n <p> </p>\n <p> </p>\n <p align="center">This page is designed to upload a <a href="http://www.tiddlywiki.com/">TiddlyWiki<a>.</p>\n <p align="center">for details see : <a href="http://TiddlyWiki.bidix.info/#HowToUpload">TiddlyWiki.bidix.info/#HowToUpload<a>.</p> \n </body>\n </html>\n <?php\n}\nelse {\n /*\n * POST Request\n */\n \n // Recursive mkdir\n function mkdirs($dir) {\n if( is_null($dir) || $dir === "" ){\n return false;\n }\n if( is_dir($dir) || $dir === "/" ){\n return true;\n }\n if( mkdirs(dirname($dir)) ){\n return mkdir($dir);\n }\n return false;\n }\n \n // var definitions\n $uploadDir = './';\n $uploadDirError = false;\n $backupError = false;\n $optionStr = $_POST['UploadPlugin'];\n $optionArr=explode(';',$optionStr);\n $options = array();\n $backupFilename = '';\n $filename = $_FILES['userfile']['name'];\n \n // get options\n foreach($optionArr as $o) {\n list($key, $value) = split('=', $o);\n $options[$key] = $value;\n }\n \n // authenticate User\n if ((!$AUTHENTICATE_USER) \n || (($options['user']) && ($options['password']) && ($USERS[$options['user']] == $options['password']))) {\n if (file_exists($filename . ".lock")) {\n echo "LockError : $filename is locked(see: http://tiddlywiki.bidix.info/#GroupAuthoring). \sn";\n exit;\n }\n // make uploadDir\n if ($options['uploaddir']) {\n if (! is_dir($options['uploaddir'])) {\n mkdirs($options['uploaddir']);\n }\n if (! is_dir($options['uploaddir'])) {\n $uploadDirError = "uploadDir mkdir error";\n }\n $uploadDir = $uploadDir . $options['uploaddir'];\n if ($uploadDir{strlen($uploadDir)-1} != '/') {\n $uploadDir = $uploadDir . '/';\n }\n } \n if ($filename)\n if (!$uploadDirError) {\n // backup existing file\n if (file_exists($filename) && ($options['backupDir'])) {\n if (! is_dir($options['backupDir'])) {\n mkdirs($options['backupDir']);\n if (! is_dir($options['backupDir'])) {\n $backupError = "backup mkdir error";\n }\n }\n $backupFilename = $options['backupDir'].'/'.substr($filename, 0, strpos($filename, '.'))\n .date('.Ymd.His').substr($filename,strpos($filename,'.'));\n rename($filename, $backupFilename) or ($backupError = "rename error");\n }\n // move uploaded file to uploadDir\n if (move_uploaded_file($_FILES['userfile']['tmp_name'], $filename)) {\n chmod($filename, 0644);\n if (!$backupError) {\n if($DEBUG) {\n echo "debug mode \sn\sn";\n }\n echo "0 - File successfully loaded in " .$filename. "\sn";\n echo("destfile:$filename \sn");\n if ($backupFilename)\n echo "backupfile:$backupFilename;\sn";\n $mtime = filemtime($filename);\n echo("mtime:$mtime");\n } else {\n echo "BackupError : $backupError - File successfully loaded in " .$filename. "\sn";\n }\n } \n else {\n echo "Error : " . $_FILES['error']." - File NOT uploaded !\sn";\n }\n }\n else {\n echo "UploadDirError : $uploadDirError - File NOT uploaded !\sn";\n }\n }\n else {\n echo "Error : UserName or Password do not match \sn";\n echo "UserName : [".$options['user']. "] Password : [". $options['password'] . "]\sn";\n }\n if ($DEBUG) {\n echo ("\snHere is some debugging info : \sn");\n echo("\s$filename : $filename \sn");\n echo("\s$backupFilename : $backupFilename \sn");\n print ("\s$_FILES : \sn");\n print_r($_FILES);\n print ("\s$options : \sn");\n print_r($options);\n }\n}\n//}}}\n?>
| tiddlyspot password:|<<option pasUploadPassword>>|\n| site management:|<<upload http://dpl.tiddlyspot.com/store.cgi index.html . . dpl>>//(requires tiddlyspot password)//<<br>>[[control panel|http://dpl.tiddlyspot.com/controlpanel]], [[download (go offline)|http://dpl.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]]|
''Syntax'' \n|[''where'' //whereCondition//]|\n\nThe whereCondition in the [[ForEachTiddlerMacro]]s whereClause is a (quoted) JavaScript boolean expression that specifies what tiddlers should be processed. In the whereCondition you refer to the build-in variable {{{tiddler}}} to access the "current" tiddler, i.e. the one that is currently checked. \n\nEvery tiddler of the TiddlyWiki is checked against the whereCondition. Those tiddlers that make the whereCondition return {{{true}}} are selected for further processing.\n\nWhen the where clause is empty all tiddlers are selected for further processing.\n\nE.g. you may write {{{'tiddler.title.length <= 4'}}} to select all tiddlers that have a title with 4 or less characters. Or {{{'tiddler.tags.contain("TODO")'}}} to select all tiddlers that have the tag "TODO". Of cause you may use any other valid JavaScript expression. \n\nSee also [[ForEachTiddlerExamples]].
!xargs, pipes, quotes\n\nFor reference, here's how to do that with xargs:\n{{{\n $ find . \s*.wav | xargs -n 1 -P 2 oggenc\n}}}\nHere's how to transcode ogg vorbis audio to mp3 without having an intermediate file:\n{{{\n $ oggdec -R -o - free.ogg | lame -x --preset radio - patented.mp3\n}}}\nAlso, you might want to put quotes around the argument variable in the example script like this:\n{{{\n oggenc -b 128 --downmix "$1"\n}}}\n\n!xjobs vs xargs (Neutral)\n> Try to do the following with GNU's xargs:\n>{{{\n> ls -1 *.mp3 | sed 's/\s(.*\s)\s.mp3/"\s1.mp3" > "\s1.wav"/' | xjobs -- mpg123 -s\n>}}}\nOkay then, I will:\n{{{\nls -1 *.mp3|sed 's/\s.mp3$//'|xargs -P0 -i -- mpg321 "{}.mp3" --wav "{}.wav"\n}}}\nAs a bonus, the files my version generates actually are WAV files, and not just raw audio!\n\nDid I miss something?\n\nIf you actually wanted non-WAV files:\n{{{\nls -1 *.mp3|sed 's/.mp3$//'|xargs -P0 -i -- sh -c 'mpg321 "{}.mp3" -s > "{}.wav"'\n}}}\n
[[xjobs|http://www.maier-komor.de/xjobs.html]]\n[[CLI Magic:Running multiple jobs with xjobs|http://www.linux.com/article.pl?sid=06/10/08/1814214]]\n[[xargs|xargs]] does this with -P option