text/plain\n.txt .text .js .vbs .asp .cgi .pl\n----\ntext/html\n.htm .html .hta .htx .mht\n----\ntext/comma-separated-values\n.csv\n----\ntext/javascript\n.js\n----\ntext/css\n.css\n----\ntext/xml\n.xml .xsl .xslt\n----\nimage/gif\n.gif\n----\nimage/jpeg\n.jpg .jpe .jpeg\n----\nimage/png\n.png\n----\nimage/bmp\n.bmp\n----\nimage/tiff\n.tif .tiff\n----\naudio/basic\n.au .snd\n----\naudio/wav\n.wav\n----\naudio/x-pn-realaudio\n.ra .rm .ram\n----\naudio/x-midi\n.mid .midi\n----\naudio/mp3\n.mp3\n----\naudio/m3u\n.m3u\n----\nvideo/x-ms-asf\n.asf\n----\nvideo/avi\n.avi\n----\nvideo/mpeg\n.mpg .mpeg\n----\nvideo/quicktime\n.qt .mov .qtvr\n----\napplication/pdf\n.pdf\n----\napplication/rtf\n.rtf\n----\napplication/postscript\n.ai .eps .ps\n----\napplication/wordperfect\n.wpd\n----\napplication/mswrite\n.wri\n----\napplication/msexcel\n.xls .xls3 .xls4 .xls5 .xlw\n----\napplication/msword\n.doc\n----\napplication/mspowerpoint\n.ppt .pps\n----\napplication/x-director\n.swa\n----\napplication/x-shockwave-flash\n.swf\n----\napplication/x-zip-compressed\n.zip\n----\napplication/x-gzip\n.gz\n----\napplication/x-rar-compressed\n.rar\n----\napplication/octet-stream\n.com .exe .dll .ocx
/***\n|''Name:''|AttachFilePlugin|\n|''Source:''|http://www.TiddlyTools.com/#AttachFilePlugin|\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\nStore or link binary files (such as jpg, gif, pdf or even mp3) within your TiddlyWiki document and then use them as images or links from within your tiddler content. Binary file content can be stored in three different locations:\n<<<\n#embedded in the attachment tiddler (encoded as base64)\n#on your filesystem (a 'local link' path/filename)\n#on a web server (a 'remote link' URL)\n<<<\nThe plugin creates an "attachment tiddler" for each file you attach. Regardless of where you store the binary content, your document can refer to the attachment tiddler rather than using a direct file or URL reference in your embedded image or external links, so that changing document locations will not require updating numerous tiddlers or copying files from one system to another.\n\n@@display:block;font-size:8pt;line-height:110%;Note: although you can edit an attachment tiddler, ''don't change any of the encoded content below the attachment header'', as it has been prepared for use in the rest of your document, and even changing a single character can make the attachment unusable. //If needed, you ''can'' edit the header information or even the MIME type declaration in the attachment data, but be very careful not to change any of the base64-encoded binary data.//@@\n!!!!!Inline interface (live)\n><<attach demoID>>\n!!!!!Usage\n<<<\nWhen you attach a file, a tiddler (tagged with<<tag attachment>>) is generated (using the source filename as the tiddler's title). The tiddler contains //''base64 text-encoded binary data''//, surrounded by {{{/%...%/}}} comment markers (so they are not visible when viewing the tiddler). The tiddler also includes summary details about the file: when it was attached, by whom, etc. and, if the attachment is an image file (jpg, gif, or png), the image is automatically displayed below the summary information.\n\nWith embedded data, your TW document can be completely self-contained...unfortunately, embedding just a few moderately-sized binary files using base64 text-encoding can dramatically increase the size of your document. To avoid this problem, you can create attachment tiddlers that define external local filesystem (file://) and/or remote web server (http://) 'reference' links, without embedding the binary data directly in the tiddler (i.e., uncheck "embed data" in the 'control panel').\n\nThese links provide an alternative source for the binary data: if embedded data is not found (or you are running on Internet Explorer, which does not currently support using embedded data), then the plugin tries the local filesystem reference. If a local file is not found, then the remote reference (if any) is used. This "fallback" approach also lets you 'virtualize' the external links in your document, so that you can access very large binary content such as PDFs, MP3's, and even *video* files, by using just a 'remote reference link' without embedding any data or downloading huge files to your hard disk.\n\nOf course, when you //do// download an attached file, the local copy will be used instead of accessing a remote server each time, thereby saving bandwidth and allowing you to 'go mobile' without having to edit any tiddlers to alter the link locations...\n\nLastly, though not completed (but nearly there), the plugin includes an integrated 'uploader' that will let you create a 'remote link' attachment tiddler AND transfer the local file to a remote server location in the same step!\n<<<\n!!!!!Syntax / Examples\n<<<\nTo embed attached files as images or link to them from other tiddlers, use the standard ~TiddlyWiki image syntax ({{{[img[tooltip|filename]]}}}), linked image syntax ({{{[img[tooltip|filename][tiddlername]]}}}) , or "external link" syntax ({{{[[text|URL]]}}}), replacing the filename or URL that is normally entered with the title of an attachment tiddler.\n\nembedded image data:\n>{{{[img[Meow|AttachFileSample]]}}}\n>[img[Meow|AttachFileSample]]\nembedded image data with link to larger remote image:\n>{{{[img[click for larger view|AttachFileSample][AttachFileSample2]]}}}\n>[img[click for larger view|AttachFileSample][AttachFileSample2]]\n'external' link to embedded image data:\n>{{{[[click to view attachment|AttachFileSample]]}}}\n>[[click to view attachment|AttachFileSample]]\n'external' link to remote image:\n>{{{[[click to view attachment|AttachFileSample2]]}}}\n>[[click to view attachment|AttachFileSample2]]\nregular ~TiddlyWiki links to attachment tiddlers:\n>{{{[[AttachFileSample]]}}} [[AttachFileSample]]\n>{{{[[AttachFileSample2]]}}} [[AttachFileSample2]]\n<<<\n!!!!!Defining MIME types and Server Scripts\n<<<\nWhen you select a source file, a ''[[MIME|http://en.wikipedia.org/wiki/MIME]]'' file type is automatically suggested, based on filename extension. The AttachFileMIMETypes tiddler defines the list of MIME types that will be recognized by the plugin. Each MIME type definition consists of exactly two lines of text: the official MIME type designator (e.g., "text/plain", "image/gif", etc.), and a space-separated list of file extensions associated with that type. List entries are separated by "----" (horizontal rules).\n\nTo upload files, a script must first be installed on a remote server so it can receive and store the files online. The AttachFileServerScripts tiddler defines the list of ''server scripts'' that will be available for you to select from when attaching and uploading a file. The list format is as described above for MIME types, except that the first line is simply the text that will appear in the ''server scripts'' droplist, while the second line is the fully-qualified URL for submitting files to that server (e.g., {{{http://www.xyz.com/path/to/cgi-bin/upload.cgi}}} or something similar).\n<<<\n!!!!!Known Limitations\n<<<\n* ''Internet Explorer does not support the use of //embedded// data for TW file attachments. However, you can still use the local/remote link definitions to create file attachments that are stored externally''\n## //while it is easy to read text files, reading binary files is not supported by IE's FileSystemObject (FSO) methods, and other file I/O techniques are subject to security barriers or require additional MS proprietary technologies (like ASP or VB) that make implementation more difficult.//\n## //IE does not support the data: URI scheme, and cannot render the embedded images or links. This would seem to be an insurmountable shortcoming in the browser. Let's hope it is added in the next version...//\n<<<\n!!!!!Installation\n<<<\nImport (or copy/paste) the following tiddlers into your document:\n* AttachFilePlugin (tagged with <<tag systemConfig>>)\n* AttachFilePluginFormatters ("distribution library") (tagged with <<tag systemConfig>>)\n* AttachFileSample and AttachFileSample2 //(sample attachment tiddler containing an image file)//\n* AttachFileMIMETypes //(defines known binary file types)//\n* AttachFileServerScripts //(remote upload server locations)//\n<<<\n!!!!!Revision History\n<<<\n''2006.09.10 [3.4.4]'' update formatters for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)\n''2006.07.24 [3.4.3]'' in prettyLink formatter, added check for isShadowTiddler() to fix problem where shadow links became external links.\n''2006.07.13 [3.4.2]'' in getAttachment(), fixed stripping of newlines so data: used in CSS will work\n''2006.05.21 [3.4.1]'' in getAttachment(), fixed substring() to extract data: URI (was losing last character, which broken rendering of SOME images)\n''2006.05.20 [3.4.0]'' hijack core getRecursiveTiddlerText() to support rendering attachments in stylesheets (e.g. {{{url([[AttachFileSample]])}}})\n''2006.05.20 [3.3.6]'' add "description" feature to easily include notes in attachment tiddler (you can always edit to add them later... but...)\n''2006.05.19 [3.3.5]'' add "attach as" feature to change default name for attachment tiddlers. Also, new optional param to specify tiddler name (disables editing)\n''2006.05.16 [3.3.0]'' completed XMLHttpRequest handling for GET or POST to configurable server scripts\n''2006.05.13 [3.2.0]'' added interface for ''upload'' feature. Major rewrite of code for clean object definitions. Major improvements in UI interaction and validation.\n''2006.05.09 [3.1.1]'' add wikifer support for using attachments in links from "linked image" syntax: {{{[img[tip|attachment1][attachment2]]}}}\n''2006.05.09 [3.1.0]'' lots of code changes: new options for attachments that use embedded data and/or links to external files (local or remote)\n''2006.05.03 [3.0.2]'' added {{{/%...%/}}} comments around attachment data to hide it when viewing attachment tiddler.\n''2006.02.05 [3.0.1]'' wrapped wikifier hijacks in initAttachmentFormatters() function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2005.12.27 [3.0.0]'' Update for TW2.0. Automatically add 'excludeMissing' tag to attachments\n''2005.12.16 [2.2.0]'' Dynamically create/remove attachPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.\n''2005.11.20 [2.1.0]'' added wikifier handler extensions for "image" and "prettyLink" to render tiddler attachments\n''2005.11.09 [2.0.0]'' begin port from old ELS Design plugin/adaptation hybrid based on ~TW1.2.33\n''2005.08.05 [1.1.0]'' moved CSS and HTML definitions into plugin code tiddler instead of using separate tiddlers\n''2005.07.27 [1.0.2]'' core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]'' added parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]'' Initial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // version\n//{{{\nversion.extensions.attach = {major: 3, minor: 4, revision: 4, date: new Date(2006,9,10)};\n//}}}\nconfig.macros.attach = {\n// // configuration\n//{{{\n hideUpload: false,\n//}}}\n// // lingo\n//{{{\n label: "attach file",\n tooltip: "Attach a file to this document",\n linkTooltip: "Attachment: ",\n\n scriptList: "AttachFileServerScripts",\n typeList: "AttachFileMIMETypes",\n\n titlePrompt: " enter tiddler title...",\n MIMEPrompt: "<option value=''>select MIME type...</option><option value='editlist'>[edit list...]</option>",\n localPrompt: " enter local path/filename...",\n URLPrompt: " enter remote URL...",\n scriptPrompt: "<option value=''>select server script...</option><option value='editlist'>[edit list...]</option>",\n targetPrompt: " enter remote path/filename...",\n\n tiddlerErr: "Please enter a tiddler title",\n sourceErr: "Please enter a source path/filename",\n storageErr: "Please select a storage method: embedded, local or remote",\n MIMEErr: "Unrecognized file format. Please select a MIME type",\n localErr: "Please enter a local path/filename",\n URLErr: "Please enter a remote URL",\n scriptErr: "Please select a server script",\n targetErr: "Please enter a remote target path/filename",\n notSupportedErr: "Sorry, this browser does not support embedded data.\snPlease uncheck 'embed data' and use a local and/or remote link instead.",\n\n sourceReport: "| source file|{{{%0}}}|\sn",\n nosourceReport: "| source file|//none//|\sn",\n dateReport: "| attached on|%0 by %1|\sn",\n notesReport: "| description|%0|\sn",\n dataReport: "| embedded data|[[%0|%0]] - {{{type=%1, size=%2 bytes, encoded=%3 bytes}}}|\sn",\n nodataReport: "| embedded data|//none//|\sn",\n localReport: "| local link|/%LOCAL_LINK%/[[%0|%1]]|\sn",\n nolocalReport: "| local link|//none//|\sn",\n URLReport: "| remote link|/%REMOTE_LINK%/[[%0|%0]]|\sn",\n noURLReport: "| remote link|//none//|\sn",\n\n uploadReport: "upload\sn<<<\sn__server script__\sn''%0''\sn{{{%1}}}\sn__remote path/filename__\sn{{{%2}}}\sn__transfer log__\sn%3/%RESULT%/\sn<<<\sn",\n\n imageReport: "image\sn<<<\snusage: {{{[img[tooltip|%0]] or [img[tooltip|%0][link]]}}}\sn[img[tooltip|%0]]\sn<<<\sn",\n dataBlock: "\sn/% DO NOT EDIT BELOW THIS POINT\sn---BEGIN_DATA---\sn%0;base64,\sn%1\sn---END_DATA---\sn%/",\n//}}}\n// // macro definition\n//{{{\n handler:\n function(place,macroName,params) {\n if (params && !params[0]) { createTiddlyButton(place,this.label,this.tooltip,this.toggleAttachPanel); return; }\n var id=params.shift();\n this.createAttachPanel(place,id+"_attachPanel",params);\n document.getElementById(id+"_attachPanel").style.position="static";\n document.getElementById(id+"_attachPanel").style.display="block";\n },\n//}}}\n//{{{\n createAttachPanel:\n function(place,panel_id,params) {\n if (!panel_id || !panel_id.length) var panel_id="_attachPanel";\n // remove existing panel (if any)\n var panel=document.getElementById(panel_id); if (panel) panel.parentNode.removeChild(panel);\n // set styles for this panel\n setStylesheet(this.css,"attachPanel");\n // create new panel\n var title=""; if (params && params[0]) title=params.shift();\n var types=this.MIMEPrompt+this.formatListOptions(store.getTiddlerText(this.typeList)); // get MIME types\n var scripts=this.scriptPrompt+this.formatListOptions(store.getTiddlerText(this.scriptList)); // get server scripts\n panel=createTiddlyElement(place,"span",panel_id,"attachPanel",null);\n var html=this.html.replace(/%id%/g,panel_id);\n html=html.replace(/%title%/g,title);\n html=html.replace(/%disabled%/g,title.length?"disabled":"");\n html=html.replace(/%types%/g,types);\n html=html.replace(/%scripts%/g,scripts);\n panel.innerHTML=html;\n return panel;\n },\n//}}}\n//{{{\n toggleAttachPanel:\n function (e) {\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("_attachPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=config.macros.attach.createAttachPanel(parent,"_attachPanel");\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n },\n//}}}\n//{{{\n formatListOptions:\n function(text,getparams) {\n if (!text || !text.trim().length) return "";\n // get server script list content from tiddler\n var parts=text.split("\sn----\sn");\n var out="";\n this.scriptParams=["","",""]; // first 3 list items: blank, prompt, editlist\n for (var p=0; p<parts.length; p++) {\n var lines=parts[p].split("\sn");\n var label=lines.shift(); // 1st line=display text\n var URL=lines.shift(); // 2nd line=item value\n var params=lines.join("\sn").replace(/<<<\sn/g,"").replace(/\sn<<</g,""); // extra lines=script params inside blockquotes\n this.scriptParams.push(params?params:"");\n out +='<option value="%1">%0</option>'.format([label,URL]);\n }\n return out;\n },\n//}}}\n// // interface definition\n//{{{\n css:\n ".attachPanel { display: none; position:absolute; z-index:10; width:35em; right:105%; top:0em;\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 .attachPanel form { display:inline;border:0;padding:0;margin:0; }\s\n .attachPanel select { width:99%;margin:0px;font-size:8pt;line-height:110%;}\s\n .attachPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n .attachPanel textarea { width:98%;margin:0px;height:2em;font-size:8pt;line-height:110%}\s\n .attachPanel table { width:100%;border:0;margin:0;padding:0;color:inherit; }\s\n .attachPanel tbody, .attachPanel tr, .attachPanel td { border:0;margin:0;padding:0;color:#000; }\s\n .attachPanel .box { border:1px solid black; padding:.3em; margin:.3em 0px; background:#f8f8f8; -moz-border-radius:5px; }\s\n .attachPanel .chk { width:auto;border:0; }\s\n .attachPanel .btn { width:auto; }\s\n .attachPanel .btn2 { width:49%; }\s\n ",\n//}}}\n//{{{\n html:\n '<form>\s\n attach from source file <input type="file" name="source" size=56 onChange="config.macros.attach.onChangeSource(this)">\s\n <div class="box">\s\n <table><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n embed data <input type=checkbox class=chk name="useData"\s\n onclick="if (!this.form.MIMEType.value.length)\s\n this.form.MIMEType.selectedIndex=this.checked?1:0; "> \s\n </td><td>\s\n <select size=1 name="MIMEType" \s\n onchange="this.title=this.value; if (this.value==\s'editlist\s')\s\n { this.selectedIndex=this.form.useData.checked?1:0; story.displayTiddler(null,config.macros.attach.typeList,2); return; }">\s\n <option value=""></option>\s\n %types%\s\n </select>\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n local link <input type=checkbox class=chk name="useLocal"\s\n onclick="this.form.local.value=this.form.local.defaultValue=this.checked?config.macros.attach.localPrompt:\s'\s';"> \s\n </td><td>\s\n <input type=text name="local" size=15 autocomplete=off value=""\s\n onchange="this.form.useLocal.checked=this.value.length" \s\n onkeyup="this.form.useLocal.checked=this.value.length" \s\n onfocus="if (!this.valuelength) this.value=config.macros.attach.localPrompt; this.select()">\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n remote link <input type=checkbox class=chk name="useURL"\s\n onclick="this.form.URL.value=this.form.URL.defaultValue=this.checked?config.macros.attach.URLPrompt:\s'\s';\s\n config.macros.attach.toggleUploadControls(\s'%id%\s',this.checked);"> \s\n </td><td>\s\n <input type=text name="URL" size=15 autocomplete=off value=""\s\n onfocus="if (!this.value.length) this.value=config.macros.attach.URLPrompt; this.select()"\s\n onchange="this.form.useURL.checked=this.value.length;\s\n config.macros.attach.toggleUploadControls(\s'%id%\s',this.value.length);"\s\n onkeyup="this.form.useURL.checked=this.value.length;\s\n config.macros.attach.toggleUploadControls(\s'%id%\s',this.value.length);">\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n <div id="%id%_upcheck" style="display:none">\s\n upload file <input type=checkbox class=chk name="upload"\s\n onclick="this.form.uploadScript.selectedIndex=this.checked?1:0;\s\n this.form.uploadScript.title=\s'\s';\s\n this.form.uploadTarget.disabled=!this.checked;\s\n this.form.uploadTarget.value=this.form.uploadTarget.defaultValue=this.checked?config.macros.attach.targetPrompt:\s'\s';\s"> \s\n </div>\s\n </td><td>\s\n <div id="%id%_uplist" style="display:none">\s\n <select size=1 name="uploadScript"\s\n onchange="this.title=this.value; if (this.value==\s'editlist\s')\s\n { this.selectedIndex=this.form.upload.checked?1:0; story.displayTiddler(null,config.macros.attach.scriptList,2); return; }\s\n this.form.upload.checked=this.value.length;\s\n if (!this.form.uploadTarget.value.length && this.value.length)\s\n this.form.uploadTarget.value=this.form.uploadTarget.defaultValue=config.macros.attach.targetPrompt;\s\n this.form.uploadTarget.disabled=!this.value.length;">\s\n <option value=""></option>\s\n %scripts%\s\n </select>\s\n </div>\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n <div id="%id%_saveas" style="display:none">save as </div>\s\n </td><td>\s\n <input type=text name="uploadTarget" id="%id%_uptarget" size=15 autocomplete=off value="" disabled\s\n onfocus="if (!this.value.length) this.value=config.macros.attach.targetPrompt; this.select()" style="display:none">\s\n </td></tr></table>\s\n </div>\s\n <table><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n attach as \s\n </td><td colspan=2>\s\n <input type=text name="tiddlertitle" size=15 autocomplete=off value="%title%"\s\n onkeyup="if (!this.value.length) { this.value=config.macros.attach.titlePrompt; this.select(); }"\s\n onfocus="if (!this.value.length) this.value=config.macros.attach.titlePrompt; this.select()" %disabled%>\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n description \s\n </td><td colspan=2>\s\n <input type=text name="notes" size=15 autocomplete=off>\s\n </td></tr><tr><td style="text-align:right;width:1%;white-space:nowrap">\s\n add tags \s\n </td><td>\s\n <input type=text name="tags" size=15 autocomplete=off value="" onfocus="this.select()">\s\n </td><td style="width:40%;text-align:right">\s\n <input type=button class=btn2 value="attach"\s\n onclick="config.macros.attach.onClickAttach(this)"><!--\s\n --><input type=button class=btn2 value="close"\s\n onclick="var panel=document.getElementById(\s'%id%\s'); if (panel) panel.parentNode.removeChild(panel);">\s\n </td></tr></table>\s\n </form>',\n//}}}\n// // control processing\n//{{{\n onChangeSource:\n function(here) {\n var form=here.form;\n var list=form.MIMEType;\n var theFilename = form.source.value;\n var theExtension = theFilename.substr(theFilename.lastIndexOf('.')).toLowerCase();\n for (var i=0; i<list.options.length; i++)\n if (list.options[i].value.indexOf(theExtension)!=-1) {\n list.selectedIndex = i;\n form.useData.checked = true;\n form.useLocal.checked = true;\n form.local.value = theFilename;\n break;\n }\n theFilename=theFilename.replace(/\s\s/g,"/"); // fixup: change \s to /\n if (!form.tiddlertitle.disabled)\n form.tiddlertitle.value=theFilename.substr(theFilename.lastIndexOf('/')+1); // get tiddlername from filename\n },\n//}}}\n//{{{\n toggleUploadControls:\n function(id,show) {\n if (config.macros.attach.hideUpload) return;\n document.getElementById(id+'_upcheck').style.display\n =document.getElementById(id+'_uplist').style.display\n =document.getElementById(id+'_saveas').style.display\n =document.getElementById(id+'_uptarget').style.display\n =show?'block':'none';\n },\n//}}}\n//{{{\n onClickAttach:\n function (here) {\n clearMessage();\n // get input values\n var form=here.form;\n var theDate=(new Date()).formatString(config.macros.timeline.dateFormat);\n var theSource = form.source.value!=form.source.defaultValue?form.source.value:"";\n var theTitle=form.tiddlertitle.value;\n var theLocal = form.local.value!=form.local.defaultValue?form.local.value:"";\n var theURL = form.URL.value!=form.URL.defaultValue?form.URL.value:"";\n var theNotes = form.notes.value;\n var theTags = "attachment excludeMissing "+form.tags.value;\n var useData=form.useData.checked;\n var useLocal=form.useLocal.checked;\n var useURL=form.useURL.checked;\n var upload=form.upload.checked;\n var theMIMEType = form.MIMEType.value.length?form.MIMEType.options[form.MIMEType.selectedIndex].text:"";\n // validate checkboxes and get filename\n if (useData||upload) {\n if (theSource.length) { if (!theLocation) var theLocation=theSource; }\n else { alert(this.sourceErr); form.source.focus(); return false; }\n }\n if (useLocal) {\n if (theLocal.length) { if (!theLocation) var theLocation = theLocal; }\n else { alert(this.localErr); form.local.focus(); return false; }\n }\n if (useURL) {\n if (theURL.length) { if (!theLocation) var theLocation = theURL; }\n else { alert(this.URLErr); form.URL.focus(); return false; }\n }\n if (!(useData||useLocal||useURL))\n { form.useData.focus(); alert(this.storageErr); return false; }\n if (!theLocation)\n { form.source.focus(); alert(this.sourceErr); return false; }\n if (!theTitle || !theTitle.trim().length || theTitle==this.titlePrompt)\n { form.tiddlertitle.focus(); alert(this.tiddlerErr); return false; }\n if (upload) {\n var theScript = form.uploadScript.value!=form.uploadScript.defaultValue?form.uploadScript.value:"";\n if (!theScript.length) { alert(this.scriptErr); form.uploadScript.focus(); return false; }\n var theServer = form.uploadScript.options[form.uploadScript.selectedIndex].text;\n var theParams = this.scriptParams[form.uploadScript.selectedIndex];\n var theTarget = form.uploadTarget.value!=form.uploadTarget.defaultValue?form.uploadTarget.value:"";\n if (!theTarget.length) { alert(this.targetErr); form.uploadTarget.focus(); return false; }\n }\n // if not already selected, determine MIME type based on filename extension (if any)\n if (!theMIMEType.length && theLocation.lastIndexOf('.')!=-1) {\n var theExt = theLocation.substr(theLocation.lastIndexOf('.')).toLowerCase();\n var theList=form.MIMEType;\n for (var i=0; i<theList.options.length; i++)\n if (theList.options[i].value.indexOf(theExt)!=-1)\n { var theMIMEType=theList.options[i].text; theList.selectedIndex=i; break; }\n }\n // encode the data\n if (useData) {\n if (!theMIMEType.length) {\n alert(this.MIMEErr);\n form.MIMEType.selectedIndex=1; form.MIMEType.focus();\n return false;\n }\n var theData = this.readFile(theSource); if (!theData) { alert(this.notSupportedErr); return false; }\n displayMessage('encoding '+theSource);\n var theEncoded = this.encodeBase64(theData);\n displayMessage('file size='+theData.length+' bytes, encoded size='+theEncoded.length+' bytes');\n }\n // upload the file\n if (upload) var uploadresult=this.uploadFile(theTitle,theSource,theMIMEType,theServer,theScript,theParams,theTarget);\n // generate tiddler and refresh\n var theText = "";\n theText +=theSource.length?this.sourceReport.format([theSource]):this.nosourceReport;\n theText +=this.dateReport.format([theDate,config.options.txtUserName]);\n theText +=theNotes.length?this.notesReport.format([theNotes]):"";\n theText +=useData?this.dataReport.format([theTitle,theMIMEType,theData.length,theEncoded.length]):this.nodataReport;\n theText +=useLocal?this.localReport.format([theLocal,'file:///'+theLocal.replace(/\s\s/g,"/")]):this.nolocalReport;\n theText +=useURL?this.URLReport.format([theURL]):this.noURLReport;\n theText +=(theMIMEType.substr(0,5)=="image")?this.imageReport.format([theTitle]):"";\n theText +=upload?uploadresult:"";\n theText +=useData?this.dataBlock.format([theMIMEType,theEncoded]):"";\n store.saveTiddler(theTitle,theTitle,theText,config.options.txtUserName,new Date(),theTags);\n document.getElementById("attachPanel").style.display="none";\n story.displayTiddler(null,theTitle);\n story.refreshTiddler(theTitle,null,true);\n displayMessage('attached "'+theTitle+'"');\n return true;\n },\n//}}}\n// // base64 conversion\n//{{{\n encodeBase64:\n function (theData) {\n if (!theData) return null;\n // encode as base64\n var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";\n var out = ""; //This is the output\n var chr1, chr2, chr3 = ""; //These are the 3 bytes to be encoded\n var enc1, enc2, enc3, enc4 = ""; //These are the 4 encoded bytes\n for (var count=0,i=0; i<theData.length; )\n {\n chr1 = theData.charCodeAt(i++); //Grab the first byte\n chr2 = theData.charCodeAt(i++); //Grab the second byte\n chr3 = theData.charCodeAt(i++); //Grab the third byte\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n if (isNaN(chr2))\n enc3 = enc4 = 64;\n else if (isNaN(chr3))\n enc4 = 64;\n out += keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4);\n chr1 = chr2 = chr3 = "";\n enc1 = enc2 = enc3 = enc4 = "";\n count+=4; if (count>60) { out+='\sn'; count=0; } // add line break every 60 chars for readability\n }\n return out;\n },\n//}}}\n// // I/O functions\n//{{{\n readFile:\n function(filePath) {\n if(!window.Components) { return(null); }\n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");\n var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);\n file.initWithPath(filePath);\n if (!file.exists()) { alert("File not found: "+filePath); return(null); }\n var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);\n inputStream.init(file, 0x01, 00004, null);\n var bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);\n bInputStream.setInputStream(inputStream);\n return(bInputStream.readBytes(inputStream.available()));\n }\n catch(e) { alert("An error occured while attempting to attach\sn"+filePath+"\sn\sn" + e); }\n return(null);\n },\n//}}}\n//{{{\n writeFile:\n function(filepath,data) {\n // TBD: decode base64 and write data to specified local path/filename\n return(false);\n },\n//}}}\n//{{{\n uploadFile:\n function(title,source,MIMEType,server,URL,scriptparams,target) {\n displayMessage("begin upload: \s""+title+"\s"");\n if (URL==undefined || !URL.length)\n return this.uploadReport.format([server,URL,target,"error: missing script URL"]);\n var x; // XML object\n try {x = new XMLHttpRequest()}\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")}\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")}\n catch (e) { return this.uploadReport.format([server,URL,target,"error: could not create XMLHttpRequest object"]); }\n }\n }\n var starttime=new Date();\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n var endtime=new Date();\n var elapsed=(endtime-starttime+1)/1000;\n displayMessage("end upload: \s""+title+"\s" ("+elapsed+" seconds)");\n var response="\sn''"+endtime.formatString("DD MMM YYYY 0hh:0mm:0ss")+"'' - upload ended (elapsed="+elapsed+" seconds).\sn";\n; response+="status code="+x.status+"\snserver response:\sn{{{\sn"+x.responseText+"\sn}}}\sn";\n var tiddler=store.getTiddler(title);\n if (tiddler) {\n var marker="/%RESULT%/"; var pos=tiddler.text.indexOf(marker);\n if (pos!=-1) {\n tiddler.set(null,tiddler.text.substr(0,pos)+response+tiddler.text.substr(pos+marker.length));\n story.displayTiddler(null,title); story.refreshTiddler(title,null,true); store.setDirty(true);\n } \n }\n }\n }\n if ((document.location.protocol=="file:") && (typeof(netscape)!="undefined")) { // UniversalBrowserRead only works from a local file context\n try { netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead')}\n catch (e) { displayMessage(e.description?e.description:e.toString()); }\n }\n try {\n var data=this.readFile(source);\n if (!data) return this.uploadReport.format([server,URL,target,"could not read local source file"]);\n scriptparams=scriptparams.replace(/%TARGET%/g,target).replace(/%TYPE%/g,MIMEType).replace(/%SIZE%/g,data.length);\n if (scriptparams.indexOf("\sn")==-1) { // single-line params=GET\n x.open("GET",URL,true);\n scriptparams=scriptparams.replace(/%DATA%/g,encodeURIComponent(data));\n x.setRequestHeader('Content-type','application/x-www-form-urlencoded');\n }\n else { // multi-line params=POST\n x.open("POST",URL,true);\n var boundary="----------AttachFilePluginDataBoundary----------";\n scriptparams="\sn"+scriptparams.replace(/%BOUNDARY%/g,boundary).replace(/%DATA%/g,data)+"\sn";\n x.setRequestHeader('Content-Length',scriptparams.length);\n x.setRequestHeader('Content-Type','multipart/form-data; boundary='+boundary);\n }\n x.send(scriptparams);\n // DEBUG alert("params\sn-----\sn"+scriptparams+"\sn-----\sn"); // wffl DEBUG\n }\n catch (e) { displayMessage(e.description?e.description:e.toString()); }\n var response="''"+starttime.formatString("DD MMM YYYY 0hh:0mm:0ss")+"'' - upload started...";\n return this.uploadReport.format([server,URL,target,response]);\n }\n};\n//}}}\n\n/***\n!!!!!Formatters\n|NOTE: These functions are also defined separately in a small, "run-time library" plugin: AttachFilePluginFormatters, which provides "stand-alone" processing for //rendering// attachment tiddlers, but does not include the AttachTiddlers control panel and supporting functions. To reduce your document size, you can include AttachFilePluginFormatters ''instead of'' AttachFilePlugin when distributing documents that contain attachments, as long you don't intend to create any new attachment tiddlers to your document.|\n\n''Extends wikify() formatters to process attachment tiddler references''\n* embedded images: {{{[img[tooltip|image]]}}}\n* linked embedded images: {{{[img[tooltip|image][link]]}}}\n* external/"pretty" links: {{{[[label|link]]}}}\n\n***/\n//{{{\nif (config.macros.attach==undefined) config.macros.attach= { };\n//}}}\n//{{{\nif (config.macros.attach.isAttachment==undefined) config.macros.attach.isAttachment=function (title) {\n var tiddler = store.getTiddler(title);\n if (tiddler==undefined || tiddler.tags==undefined) return false;\n return (tiddler.tags.find("attachment")!=null);\n}\n//}}}\n//{{{\nif (config.macros.attach.getAttachment==undefined) config.macros.attach.getAttachment=function(title) {\n var text = store.getTiddlerText(title);\n var result=""; var pos=0; var endpos=0;\n\n var startmarker="---BEGIN_DATA---\sn";\n var endmarker="\sn---END_DATA---";\n if (!config.browser.isIE && (pos=text.indexOf(startmarker))!=-1 && (endpos=text.indexOf(endmarker))!=-1) {\n var out="data:"+(text.substring(pos+startmarker.length,endpos)).replace(/\sn/g,''); // strip embedded newlines\n return out;\n }\n if ((pos=text.indexOf("/%LOCAL_LINK%/"))!=-1) // fallback to local link\n return text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos)); \n if ((pos=text.indexOf("/%REMOTE_LINK%/"))!=-1) // fallback to remote URL\n return text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));\n\n // fallback for backward-compatibility:\n // before 3.2.0 encoded datablock was located between ----'s instead of using embedded 'keyword markers' in the tiddler content\n var data=text.split('\sn----\sn');\n if (!config.browser.isIE && data[1] && data[1].length) // NOTE: IE does not support the "data:" URI scheme\n return "data:"+data[1].replace(/\s\sn/g,'');\n\n return "";\n}\n//}}}\n//{{{\nif (config.macros.attach.init_formatters==undefined) config.macros.attach.init_formatters=function() {\n if (this.initialized) return;\n // find the formatter for "image" and replace the handler\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="image"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n if (!this.lookaheadRegExp) // fixup for TW2.0.x\n this.lookaheadRegExp = new RegExp(this.lookahead,"mg");\n this.lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = this.lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link\n {\n var e = w.output;\n if(lookaheadMatch[5])\n {\n var link = lookaheadMatch[5];\n // ELS -------------\n if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x\n var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);\n else\n var external=config.formatterHelpers.isExternalLink(link);\n if (external)\n {\n if (config.macros.attach.isAttachment(link))\n {\n e = createExternalLink(w.output,link);\n e.href=config.macros.attach.getAttachment(link);\n e.title = config.macros.attach.linkTooltip + link;\n }\n else\n e = createExternalLink(w.output,link);\n }\n else \n e = createTiddlyLink(w.output,link,false,null,w.isStatic);\n // ELS -------------\n addClass(e,"imageLink");\n }\n var img = createTiddlyElement(e,"img");\n if(lookaheadMatch[1])\n img.align = "left";\n else if(lookaheadMatch[2])\n img.align = "right";\n if(lookaheadMatch[3])\n img.title = lookaheadMatch[3];\n img.src = lookaheadMatch[4];\n // ELS -------------\n if (config.macros.attach.isAttachment(lookaheadMatch[4]))\n img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);\n // ELS -------------\n w.nextMatch = this.lookaheadRegExp.lastIndex;\n }\n }\n//}}}\n//{{{\n // find the formatter for "prettyLink" and replace the handler\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="prettyLink"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n if (!this.lookaheadRegExp) // fixup for TW2.0.x\n this.lookaheadRegExp = new RegExp(this.lookahead,"mg");\n this.lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = this.lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n var e;\n var text = lookaheadMatch[1];\n if (lookaheadMatch[2]) // Simple bracketted link\n {\n e = createTiddlyLink(w.output,text,false,null,w.isStatic);\n }\n else if(lookaheadMatch[3]) // Pretty bracketted link\n {\n var link = lookaheadMatch[4];\n // ELS -------------\n if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x\n var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);\n else\n var external=config.formatterHelpers.isExternalLink(link);\n if (external)\n {\n if (config.macros.attach.isAttachment(link))\n {\n e = createExternalLink(w.output,link);\n e.href=config.macros.attach.getAttachment(link);\n e.title = config.macros.attach.linkTooltip + link;\n }\n else\n e = createExternalLink(w.output,link);\n }\n else \n e = createTiddlyLink(w.output,link,false,null,w.isStatic);\n // ELS -------------\n }\n createTiddlyText(e,text);\n w.nextMatch = this.lookaheadRegExp.lastIndex;\n }\n }\n this.initialized=true;\n}\n//}}}\n//{{{\nconfig.macros.attach.init_formatters(); // load time init\n//}}}\n//{{{\nif (TiddlyWiki.prototype.coreGetRecursiveTiddlerText==undefined) {\n TiddlyWiki.prototype.coreGetRecursiveTiddlerText = TiddlyWiki.prototype.getRecursiveTiddlerText;\n TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth) {\n return config.macros.attach.isAttachment(title)?\n config.macros.attach.getAttachment(title):this.coreGetRecursiveTiddlerText(title,defaultText,depth);\n }\n}\n//}}}
/***\n|''Name:''|AttachFilePluginFormatters|\n|''Source:''|http://www.TiddlyTools.com/#AttachFilePluginFormatters|\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\nYou can include this small //''run time library''// in your documents to render ''attachment tiddlers'' created by the AttachFilePlugin. Attachment tiddlers are tagged with<<tag attachment>>and contain binary file content (e.g., jpg, gif, pdf, mp3, etc.) that can be stored directly as base64 text-encoded data or loaded from external files stored on a local filesystem or remote web server.\n\nThis plugin extends the behavior of the following TiddlyWiki core "wikify()" formatters:\n* embedded images: {{{[img[tooltip|image]]}}}\n* linked embedded images: {{{[img[tooltip|image][link]]}}}\n* external/"pretty" links: {{{[[label|link]]}}}\n\n''Please refer to AttachFilePlugin (source: http://www.TiddlyTools.com/#AttachFilePlugin) for additional information.''\n!!!!!Revision History\n<<<\n''2006.09.10 [3.4.4.0]'' sync with AttachFilePlugin v3.4.3\n''2006.07.24 [3.4.3.0]'' sync with AttachFilePlugin v3.4.3\n''2006.07.13 [3.4.2.0]'' sync with AttachFilePlugin v3.4.2\n''2006.06.15 [3.4.1.0]'' sync with AttachFilePlugin v3.4.1\n''2006.05.20 [3.4.0.0]'' sync with AttachFilePlugin v3.4.0\n''2006.05.13 [3.2.0.0]'' created from AttachFilePlugin v3.2.0\n<<<\n!!!!!Code\n***/\n//{{{\nif (config.macros.attach==undefined) config.macros.attach= { };\n//}}}\n//{{{\nif (config.macros.attach.isAttachment==undefined) config.macros.attach.isAttachment=function (title) {\n var tiddler = store.getTiddler(title);\n if (tiddler==undefined || tiddler.tags==undefined) return false;\n return (tiddler.tags.find("attachment")!=null);\n}\n//}}}\n//{{{\nif (config.macros.attach.getAttachment==undefined) config.macros.attach.getAttachment=function(title) {\n var text = store.getTiddlerText(title);\n var result=""; var pos=0; var endpos=0;\n\n var startmarker="---BEGIN_DATA---\sn";\n var endmarker="\sn---END_DATA---";\n if (!config.browser.isIE && (pos=text.indexOf(startmarker))!=-1 && (endpos=text.indexOf(endmarker))!=-1) {\n var out="data:"+(text.substring(pos+startmarker.length,endpos)).replace(/\sn/g,''); // strip embedded newlines\n return out;\n }\n if ((pos=text.indexOf("/%LOCAL_LINK%/"))!=-1) // fallback to local link\n return text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos)); \n if ((pos=text.indexOf("/%REMOTE_LINK%/"))!=-1) // fallback to remote URL\n return text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));\n\n // fallback for backward-compatibility:\n // before 3.2.0 encoded datablock was located between ----'s instead of using embedded 'keyword markers' in the tiddler content\n var data=text.split('\sn----\sn');\n if (!config.browser.isIE && data[1] && data[1].length) // NOTE: IE does not support the "data:" URI scheme\n return "data:"+data[1].replace(/\s\sn/g,'');\n\n return "";\n}\n//}}}\n//{{{\nif (config.macros.attach.init_formatters==undefined) config.macros.attach.init_formatters=function() {\n if (this.initialized) return;\n // find the formatter for "image" and replace the handler\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="image"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n if (!this.lookaheadRegExp) // fixup for TW2.0.x\n this.lookaheadRegExp = new RegExp(this.lookahead,"mg");\n this.lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = this.lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link\n {\n var e = w.output;\n if(lookaheadMatch[5])\n {\n var link = lookaheadMatch[5];\n // ELS -------------\n if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x\n var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);\n else\n var external=config.formatterHelpers.isExternalLink(link);\n if (external)\n {\n if (config.macros.attach.isAttachment(link))\n {\n e = createExternalLink(w.output,link);\n e.href=config.macros.attach.getAttachment(link);\n e.title = config.macros.attach.linkTooltip + link;\n }\n else\n e = createExternalLink(w.output,link);\n }\n else \n e = createTiddlyLink(w.output,link,false,null,w.isStatic);\n // ELS -------------\n addClass(e,"imageLink");\n }\n var img = createTiddlyElement(e,"img");\n if(lookaheadMatch[1])\n img.align = "left";\n else if(lookaheadMatch[2])\n img.align = "right";\n if(lookaheadMatch[3])\n img.title = lookaheadMatch[3];\n img.src = lookaheadMatch[4];\n // ELS -------------\n if (config.macros.attach.isAttachment(lookaheadMatch[4]))\n img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);\n // ELS -------------\n w.nextMatch = this.lookaheadRegExp.lastIndex;\n }\n }\n//}}}\n//{{{\n // find the formatter for "prettyLink" and replace the handler\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="prettyLink"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n if (!this.lookaheadRegExp) // fixup for TW2.0.x\n this.lookaheadRegExp = new RegExp(this.lookahead,"mg");\n this.lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = this.lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n var e;\n var text = lookaheadMatch[1];\n if (lookaheadMatch[2]) // Simple bracketted link\n {\n e = createTiddlyLink(w.output,text,false,null,w.isStatic);\n }\n else if(lookaheadMatch[3]) // Pretty bracketted link\n {\n var link = lookaheadMatch[4];\n // ELS -------------\n if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x\n var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);\n else\n var external=config.formatterHelpers.isExternalLink(link);\n if (external)\n {\n if (config.macros.attach.isAttachment(link))\n {\n e = createExternalLink(w.output,link);\n e.href=config.macros.attach.getAttachment(link);\n e.title = config.macros.attach.linkTooltip + link;\n }\n else\n e = createExternalLink(w.output,link);\n }\n else \n e = createTiddlyLink(w.output,link,false,null,w.isStatic);\n // ELS -------------\n }\n createTiddlyText(e,text);\n w.nextMatch = this.lookaheadRegExp.lastIndex;\n }\n }\n this.initialized=true;\n}\n//}}}\n//{{{\nconfig.macros.attach.init_formatters(); // load time init\n//}}}\n//{{{\nif (TiddlyWiki.prototype.coreGetRecursiveTiddlerText==undefined) {\n TiddlyWiki.prototype.coreGetRecursiveTiddlerText = TiddlyWiki.prototype.getRecursiveTiddlerText;\n TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth) {\n return config.macros.attach.isAttachment(title)?\n config.macros.attach.getAttachment(title):this.coreGetRecursiveTiddlerText(title,defaultText,depth);\n }\n}\n//}}}
test store.php\nhttp://www.tiddlytools.com/store.php\n<<<\n--%BOUNDARY%\nContent-disposition: form-data;name="UploadPlugin";\n\nbackupDir=;user=;password=;uploaddir=upload;\n--%BOUNDARY%\nContent-disposition: form-data;name="userfile";filename="%TARGET%"\nContent-Type: %TYPE%\nContent-Length: %SIZE%\n\n%DATA%\n--%BOUNDARY%--\n<<<\n----\npublish for public web access\nhttp://www.tiddlytools.com/response.txt\n<<<\n?file=%TARGET%&data=%DATA%\n<<<\n----\npublish for password-protected web access\nhttp://www.tiddlytools.com/response.txt\n<<<\n?file=%TARGET%&data=%DATA%\n<<<\n----\nsend to WebTPS report server (encrypted)\nhttps://www.WebTPS.com/reports/upload.asp\n<<<\n?workgroup=Y2K&key=3141592653589&file=%TARGET%\n<<<\n----\nsend to my Flickr account\nhttp://www.flickr.com/\n<<<\n\n<<<
[[StyleSheetAdjustments]]\n[[BrightText]]\n/* ==== blackout ==== */\n/*{{{*/\nbody\n { background-color:#000; }\n.menubox\n { background-color:#111; }\n.viewer\n { background-color:#111; border: 1px solid #999; -moz-border-radius:1em; padding:1em; }\n.header\n { background-image: none; background-color:transparent; color:#ccf; border:0; }\n.floatingPanel, .attachPanel, #importPanel, #exportPanel,\n { background: #eee; background-image: url('[[TexturesParchmentGray]]');}\n.floatingPanel a, .attachPanel a, #messageArea a, #importPanel a, #exportPanel a, #sidebarTabs .tabContents a,\n.floatingPanel .button, .attachPanel .button, #messageArea .button, #importPanel .button, #exportPanel .button, #sidebarTabs .tabContents .button,\n.floatingPanel .tiddlyLinkExisting, .attachPanel .tiddlyLinkExisting, #messageArea .tiddlyLinkExisting, #importPanel .tiddlyLinkExisting, #exportPanel .tiddlyLinkExisting, #sidebarTabs .tabContents .tiddlyLinkExisting\n { color:#009; }\n.siteMenu .floatingPanel, #messageArea \n { background: #eee; }\n.tiddlyCard { background:#ffd; }\n\n.viewer h1,.viewer h2,.viewer h3,.viewer h4,.viewer h5 { background: #666; color:#fff; }\n#sidebarTabs .tabContents\n { background-color:#111; color:#fff; }\n#sidebarTabs .tabContents a, #sidebarTabs .tabContents .button, #sidebarTabs .tabContents .tiddlyLinkExisting\n { color:#99f; }\n/*}}}*/
/***\n|''Name:''|BreadcrumbsPlugin|\n|''Description:''||\n|''Version:''|1.4.0|\n|''Date:''|Aug 02, 2006|\n|''Source:''|http://sourceforge.net/project/showfiles.php?group_id=150646|\n|''Author:''|Alan Hecht (with 2.0 update from 'jack' and revisions by Bram Chen)|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License]]|\n|''~CoreVersion:''|2.1.0|\n|''Browser:''|Firefox 1.5+; InternetExplorer 6.0|\n\n!Revision History:\n__TiddlyTools variant:__\n1.4.0.1(TT) 2006.08.04 - change spaces to tabs\n1.4.0.0(TT) 2006.08.04 - modified from 1.4.0 distro:\n<<<\nin refreshCrumbs(), set {{{display:none/block}}} instead of {{{visibility:hidden/visible}}}\nin restartHome(), check for valid crumbArea before setting style\ngeneral code cleanup/reformat using tabs to indent\n<<<\n|''Version''|''Date''|''Note''|\n|1.4.0|Aug 02, 2006|Fixed bug, the redefined onClickTiddlerLink_orig_breadCrumbs works incorrectly on IE|\n|1.3.0|Jul 20, 2006|Runs compatibly with TW 2.1.0 (rev #403+)|\n|1.2.0|Feb 07, 2006|change global array breadCrumbs to config.breadCrumbs by Eric's suggestion|\n|1.1.0|Feb 04, 2006|JSLint checked|\n|1.0.0|Feb 01, 2006|TW2 ready and code Cleaned-up|\n\n!Code section:\n***/\n//{{{\nversion.extensions.breadCrumbs = {major: 1, minor: 4, revision: 0, date: new Date("Aug 02, 2006")};\nconfig.breadCrumbs = [];\n\nwindow.onClickTiddlerLink_orig_breadCrumbs = window.onClickTiddlerLink;\nwindow.onClickTiddlerLink = function(e){\n if (!e) var e = window.event;\n window.onClickTiddlerLink_orig_breadCrumbs(e);\n addCrumb(e);\n return false;\n}\n\nfunction addCrumb(e){\n if (!e) var e = window.event;\n var thisCrumb = "[[" + resolveTarget(e).getAttribute("tiddlyLink") + "]]";\n var ind = config.breadCrumbs.find(thisCrumb);\n if(ind === null)\n config.breadCrumbs.push(thisCrumb);\n else\n config.breadCrumbs.length = ind++;\n refreshCrumbs();\n return false;\n}\n\nfunction refreshCrumbs(){\n var crumbArea = document.getElementById("breadCrumbs");\n if (!crumbArea) {\n var crumbArea = document.createElement("div");\n crumbArea.id = "breadCrumbs";\n crumbArea.style.display= "none"; // ELS changed from: crumbArea.style.visibility= "hidden";\n var targetArea = document.getElementById("tiddlerDisplay");\n targetArea.parentNode.insertBefore(crumbArea,targetArea);\n }\n crumbArea.style.display = "block"; // ELS changed from: crumbArea.style.visibility = "visible";\n removeChildren(crumbArea);\n createTiddlyButton(crumbArea,"Home",null,restartHome);\n wikify(" | " + config.breadCrumbs.join(' > '),crumbArea) // ELS: changed || to |\n}\n\nfunction restartHome(){\n story.closeAllTiddlers();\n restart();\n config.breadCrumbs = [];\n var crumbArea = document.getElementById("breadCrumbs");\n if (crumbArea) // ELS: added check to make sure crumbArea exists\n crumbArea.style.display = "none"; // ELS changed from: crumbArea.style.visibility = "hidden";\n}\n//}}}
/* background images */\n/* colors and borders */\na { color:#ccf; }\na:hover { color:#fff; }\n\n#breadCrumbs { color:#ccc; }\n#breadCrumbs a { color:#ccf; }\n#titleLine { color: #fff; }\n#titleLine a { color: #009900; }\n.siteMenu { color: #fff; border:0; margin-bottom:.5em }\n.siteMenu a, .siteMenu .button, .siteMenu .tiddlyLink { color: #ccf; }\n.storyMenu { color: #fff; border:0; margin-bottom:.5em }\n.storyMenu a, .storyMenu .button, .storyMenu .tiddlyLink { color: #ccf; }\n/*\n#mainMenu { color: #fff; }\n#mainMenu .tiddlyLink { color: #def; }\n#mainMenu .tiddlyLink:hover { color: #fff; }\n#mainMenu .externalLink { color: #def; }\n#mainMenu .externalLink:hover { color: #fff; }\n#mainMenu .button, #mainMenu A { color: #def; }\n#mainMenu .button:hover, #mainMenu A:hover { color: #fff; }\n*/\n#messageArea { color: #006; }\n#messageArea a:link, #messageArea a:visited { color: #006; }\n#messageArea a:hover { color: #f00; }\n#messageArea a:active { color: #006; }\n#popup { color: #000; }\n#popup a { color: #006; }\n#popup a:hover { color: #006; }\n#popup hr { color: #666; }\n.tabContents { color: #000; }\n.tiddler .button { color: #ccf; }\n.tiddler .button:hover { color: #fff; }\n.tiddler .button:active { color: #fff; }\n.title { color: #def; }\n.subtitle { color: #89a; }\n.toolbar { color: #aaa; }\n.footer { color: #888; }\n.selectedTiddler .footer { color: #ddd; }\n.viewer { color: #fff; }\n.viewer a:link, .viewer a:visited { color: #ccf; }\n.viewer a:hover { color: #fff; }\n.viewer .button { color: #def; }\n.viewer .button:hover { color: #fff; }\n.viewer th { color: #fff; }\n.viewer td { color: #fff; }\n.viewer code { color: #ccc; }\n.viewer pre { color: #000; }\n.viewer hr { color: #666; }\n.viewer .highlight, .viewer .marked { color: #fff; }\n.viewer .tabSelected { background-color: #014; color:#fff; border-color:#999; border-width:2px; padding-bottom:2px !important; }\n.viewer .tabUnselected { background-color: #236; color:#999; border-color:#666}\n.viewer .tabContents { background-color: #014; color:#fff; border-color:#999; border-width:2px }\n.tagging a, .tagged a, .tagging .button, .tagged .button { color: #009; }\n.highlight, .marked { color: #fff; }\n.editor { color: #402C74; }\n.editorFooter { color: #aaa; }\n.editorFooter A { color: #930; }\n.editorFooter A:hover { color: #cf6; }\n.editorFooter A:active { color: #fff; }\n#licensePanel A { color: #66f; }\n#licensePanel A:hover { color: #fff; }\n#licensePanel A:active { color: #fff; }\n.errorNoSuchMacro { color: #ff0; }\n.zoomer { color: #fff; }\n\n.floatingPanel .button,\n.floatingPanel a:link,\n.floatingPanel a:visited,\n.viewer .floatingPanel .button,\n.viewer .floatingPanel a:link,\n.viewer .floatingPanel a:visited {\n color: #009 !important;\n}\n.floatingPanel a:hover,\n.viewer .floatingPanel a:hover {\n color: #fff !important;\n}\n/***\n----\n***/\n/*{{{*/\n.tiddlyCard\n { color:#000 !important; }\n.tiddlyCard a, .tiddlyCard .button, .tiddlyCard .tiddlyLinkExisting, .tiddlyCard .tiddlyLinkNonExisting\n { color:#009 !important; }\n.attachPanel a, #importPanel a, #exportpanel a,\n.attachPanel .button, #importPanel .button, #exportpanel .button,\n.attachPanel .tiddlyLinkExisting, #importPanel .tiddlyLinkExisting, #exportpanel .tiddlyLinkExisting,\n.attachPanel .tiddlyLinkNonExisting, #importPanel .tiddlyLinkNonExisting, #exportpanel .tiddlyLinkNonExisting,\n.tab .button, .tab A,\n.tab .tiddlyLinkExisting, .tab .tiddlyLinkNonExisting\n { color:#009 !important; }\n#sidebarOptions, #sidebarOptions .sliderPanel\n { color: #fff; }\n#sidebarOptions .button, #sidebarOptions A,\n#sidebarOptions .tiddlyLinkExisting, #sidebarOptions .tiddlyLinkNonExisting,\n#sidebarOptions .sliderPanel .button, #sidebarOptions .sliderPanel A,\n#sidebarOptions .sliderPanel .tiddlyLinkExisting, #sidebarOptions .sliderPanel .tiddlyLinkNonExisting\n { color: #def; }\n#sidebarTabs, #sidebarTabs .sliderPanel, #sidebarTabs .tabContents\n { color: #fff; }\n#sidebarTabs .tabContents *[class="TOCList"] /* MOZ ONLY */\n { color:#fff !important; }\n#sidebarTabs .button, /* #sidebarTabs A, */\n#sidebarTabs .tiddlyLinkExisting, #sidebarTabs .tiddlyLinkNonExisting\n { color: #def; }\n.menubox\n { color:#fff; }\n.menubox a, .menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting\n { color:#99f !important; }\n.groupbox, .groupbox table, .groupbox tbody, .groupbox tr, .groupbox td\n { color:#000; }\n.groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting\n { color:#009 !important; }\n.floatingPanel, .floatingPanel table, .floatingPanel tbody, .floatingPanel tr, .floatingPanel td\n { color:#000; }\n/*}}}*/
/***\n|''Name:''|CalendarPlugin|\n|''Source:''|http://www.TiddlyTools.com/#CalendarPlugin|\n|''Author:''|SteveRumsby|\n|''License:''|unknown|\n|''~CoreVersion:''|2.0.10|\n\n// // updated by Jeremy Sheeley to add cacheing for reminders\n// // see http://www.geocities.com/allredfaq/reminderMacros.html\n// // ''Changes by ELS 2006.08.23:''\n// // added handling for weeknumbers (code supplied by Martin Budden. see "wn**" comment marks)\n// // ''Changes by ELS 2005.10.30:''\n// // config.macros.calendar.handler()\n// // ^^use "tbody" element for IE compatibility^^\n// // ^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^\n// // createCalendarDays()\n// // ^^use showDate() function (if defined) to render autostyled date with linked popup^^\n// // calendar stylesheet definition\n// // ^^use .calendar class-specific selectors, add text centering and margin settings^^\n\n\n!!!!!Configuration:\n<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//\n|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|\n|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|\n\n!!!!!Syntax:\n|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|\n|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|\n|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|\n|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|\n|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|\n|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|\n\n***/\n// //Modify this section to change the text displayed for the month and day names, to a different language for example. You can also change the format of the tiddler names linked to from each date, and the colours used.\n\n//{{{\nconfig.macros.calendar = {};\n\nconfig.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];\nconfig.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];\n\nconfig.macros.calendar.weekendbg = "#c0c0c0";\nconfig.macros.calendar.monthbg = "#e0e0e0";\nconfig.macros.calendar.holidaybg = "#ffc0c0";\n\n//}}}\n// //''Code section:''\n// (you should not need to alter anything below here)//\n//{{{\nif(config.options.txtCalFirstDay == undefined)\n config.options.txtCalFirstDay = 0;\nif(config.options.txtCalStartOfWeekend == undefined)\n config.options.txtCalStartOfWeekend = 5;\nif(config.options.chkDisplayWeekNumbers == undefined)//wn**\n config.options.chkDisplayWeekNumbers = false;\nif(config.options.chkDisplayWeekNumbers)\n config.options.txtCalFirstDay = 0;\n\nconfig.macros.calendar.tiddlerformat = "0DD/0MM/YYYY"; // This used to be changeable - for now, it isn't// <<smiley :-(>> \n\nversion.extensions.calendar = { major: 0, minor: 6, revision: 0, date: new Date(2006, 1, 22)};\nconfig.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\nconfig.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead\n//}}}\n\n// //Is the given date a holiday?\n//{{{\nfunction calendarIsHoliday(date)\n{\n var longHoliday = date.formatString("0DD/0MM/YYYY");\n var shortHoliday = date.formatString("0DD/0MM");\n\n for(var i = 0; i < config.macros.calendar.holidays.length; i++) {\n if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday) {\n return true;\n }\n }\n return false;\n}\n//}}}\n\n// //The main entry point - the macro handler.\n// //Decide what sort of calendar we are creating (month or year, and which month or year)\n// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.\n// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//\n// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//\n// ELS 2006.05.29: add journalDateFmt handling//\n//{{{\nconfig.macros.calendar.handler = function(place,macroName,params)\n{\n var calendar = createTiddlyElement(place, "table", null, "calendar", null);\n var tbody = createTiddlyElement(calendar, "tbody", null, null, null);\n var today = new Date();\n var year = today.getYear();\n if (year<1900) year+=1900;\n \n // get format for journal link by reading from SideBarOptions (ELS 5/29/06 - based on suggestion by Martin Budden)\n var text = store.getTiddlerText("SideBarOptions");\n this.journalDateFmt = "DD-MMM-YYYY";\n var re = new RegExp("<<(?:newJournal)([^>]*)>>","mg"); var fm = re.exec(text);\n if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }\n\n if (params[0] == "thismonth")\n {\n cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, today.getMonth());\n } \n else if (params[0] == "lastmonth") {\n var month = today.getMonth()-1; if (month==-1) { month=11; year--; }\n cacheReminders(new Date(year, month, 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, month);\n }\n else if (params[0] == "nextmonth") {\n var month = today.getMonth()+1; if (month>11) { month=0; year++; }\n cacheReminders(new Date(year, month, 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, month);\n }\n else {\n if (params[0]) year = params[0];\n if(params[1])\n {\n cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);\n createCalendarOneMonth(tbody, year, params[1]-1);\n }\n else\n {\n cacheReminders(new Date(year, 0, 1, 0, 0), 366);\n createCalendarYear(tbody, year);\n }\n }\n window.reminderCacheForCalendar = null;\n}\n//}}}\n//{{{\n//This global variable is used to store reminders that have been cached\n//while the calendar is being rendered. It will be renulled after the calendar is fully rendered.\nwindow.reminderCacheForCalendar = null;\n//}}}\n//{{{\nfunction cacheReminders(date, leadtime)\n{\n if (window.findTiddlersWithReminders == null)\n return;\n window.reminderCacheForCalendar = {};\n var leadtimeHash = [];\n leadtimeHash [0] = 0;\n leadtimeHash [1] = leadtime;\n var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);\n for(var i = 0; i < t.length; i++) {\n //just tag it in the cache, so that when we're drawing days, we can bold this one.\n window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"]; \n }\n}\n//}}}\n//{{{\nfunction createCalendarOneMonth(calendar, year, mon)\n{\n var row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);\n row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarDayHeader(row, 1);\n createCalendarDayRowsSingle(calendar, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonth(calendar, year, mon)\n{\n var row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);\n row = createTiddlyElement(calendar, "tr", null, null, null);\n createCalendarDayHeader(row, 1);\n createCalendarDayRowsSingle(calendar, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarYear(calendar, year)\n{\n var row;\n row = createTiddlyElement(calendar, "tr", null, null, null);\n var back = createTiddlyElement(row, "td", null, null, null);\n var backHandler = function() {\n removeChildren(calendar);\n createCalendarYear(calendar, year-1);\n };\n createTiddlyButton(back, "<", "Previous year", backHandler);\n back.align = "center";\n\n var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);\n yearHeader.align = "center";\n //yearHeader.setAttribute("colSpan", 19);\n yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**\n\n var fwd = createTiddlyElement(row, "td", null, null, null);\n var fwdHandler = function() {\n removeChildren(calendar);\n createCalendarYear(calendar, year+1);\n };\n createTiddlyButton(fwd, ">", "Next year", fwdHandler);\n fwd.align = "center";\n\n createCalendarMonthRow(calendar, year, 0);\n createCalendarMonthRow(calendar, year, 3);\n createCalendarMonthRow(calendar, year, 6);\n createCalendarMonthRow(calendar, year, 9);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonthRow(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);\n createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDayHeader(row, 3);\n createCalendarDayRows(cal, year, mon);\n}\n//}}}\n\n//{{{\nfunction createCalendarMonthHeader(cal, row, name, nav, year, mon)\n{\n var month;\n if(nav) {\n var back = createTiddlyElement(row, "td", null, null, null);\n back.align = "center";\n back.style.background = config.macros.calendar.monthbg;\n\n/*\n back.setAttribute("colSpan", 2);\n\n var backYearHandler = function() {\n var newyear = year-1;\n removeChildren(cal);\n cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, mon);\n };\n createTiddlyButton(back, "<<", "Previous year", backYearHandler);\n*/\n var backMonHandler = function() {\n var newyear = year;\n var newmon = mon-1;\n if(newmon == -1) { newmon = 11; newyear = newyear-1;}\n removeChildren(cal);\n cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(back, "<", "Previous month", backMonHandler);\n\n\n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n// month.setAttribute("colSpan", 3);\n// month.setAttribute("colSpan", 5);\n month.setAttribute("colSpan", config.options.chkDisplayWeekNumbers?6:5);//wn**\n\n var fwd = createTiddlyElement(row, "td", null, null, null);\n fwd.align = "center";\n fwd.style.background = config.macros.calendar.monthbg; \n\n// fwd.setAttribute("colSpan", 2);\n var fwdMonHandler = function() {\n var newyear = year;\n var newmon = mon+1;\n if(newmon == 12) { newmon = 0; newyear = newyear+1;}\n removeChildren(cal);\n cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, newmon);\n };\n createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);\n/*\n var fwdYear = createTiddlyElement(row, "td", null, null, null);\n var fwdYearHandler = function() {\n var newyear = year+1;\n removeChildren(cal);\n cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);\n createCalendarOneMonth(cal, newyear, mon);\n };\n createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);\n*/\n } else {\n month = createTiddlyElement(row, "td", null, "calendarMonthname", name)\n //month.setAttribute("colSpan", 7);\n month.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?8:7);//wn**\n }\n month.align = "center";\n month.style.background = config.macros.calendar.monthbg;\n}\n//}}}\n\n//{{{\nfunction createCalendarDayHeader(row, num)\n{\n var cell;\n for(var i = 0; i < num; i++) {\n if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, "td");//wn**\n for(var j = 0; j < 7; j++) {\n var d = j + (config.options.txtCalFirstDay - 0);\n if(d > 6) d = d - 7;\n cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);\n if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))\n cell.style.background = config.macros.calendar.weekendbg;\n }\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarDays(row, col, first, max, year, mon)\n{\n var i;\n if (config.options.chkDisplayWeekNumbers){\n if (first<=max) {\n var ww = new Date(year,mon,first);\n createTiddlyElement(row, "td", null, null, "w"+ww.getWeek());//wn**\n }\n else createTiddlyElement(row, "td", null, null, null);//wn**\n }\n for(i = 0; i < col; i++) {\n createTiddlyElement(row, "td", null, null, null);\n }\n var day = first;\n for(i = col; i < 7; i++) {\n var d = i + (config.options.txtCalFirstDay - 0);\n if(d > 6) d = d - 7;\n var daycell = createTiddlyElement(row, "td", null, null, null);\n var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);\n\n if(day > 0 && day <= max) {\n var celldate = new Date(year, mon, day);\n // ELS 2005.10.30: use <<date>> macro's showDate() function to create popup\n if (window.showDate) {\n showDate(daycell,celldate,"popup","DD",config.macros.calendar.journalDateFmt,true, isaWeekend); // ELS 5/29/06 - use journalDateFmt \n } else {\n if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;\n var title = celldate.formatString(config.macros.calendar.tiddlerformat);\n if(calendarIsHoliday(celldate)) {\n daycell.style.background = config.macros.calendar.holidaybg;\n }\n if(window.findTiddlersWithReminders == null) {\n var link = createTiddlyLink(daycell, title, false);\n link.appendChild(document.createTextNode(day));\n } else {\n var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);\n }\n }\n }\n day++;\n }\n}\n//}}}\n\n// //We've clicked on a day in a calendar - create a suitable pop-up of options.\n// //The pop-up should contain:\n// // * a link to create a new entry for that date\n// // * a link to create a new reminder for that date\n// // * an <hr>\n// // * the list of reminders for that date\n//{{{\nfunction onClickCalendarDate(e)\n{\n var button = this;\n var date = button.getAttribute("title");\n var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));\n\n date = dat.formatString(config.macros.calendar.tiddlerformat);\n var popup = createTiddlerPopup(this);\n popup.appendChild(document.createTextNode(date));\n var newReminder = function() {\n var t = store.getTiddlers(date);\n displayTiddler(null, date, 2, null, null, false, false);\n if(t) {\n document.getElementById("editorBody" + date).value += "\sn<<reminder day:" + dat.getDate() +\n " month:" + (dat.getMonth()+1) +\n " year:" + (dat.getYear()+1900) + " title: >>";\n } else {\n document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +\n " month:" + (dat.getMonth()+1) +\n " year:" + (dat.getYear()+1900) + " title: >>";\n }\n };\n var link = createTiddlyButton(popup, "New reminder", null, newReminder); \n popup.appendChild(document.createElement("hr"));\n\n var t = findTiddlersWithReminders(dat, [0,14], null, 1);\n for(var i = 0; i < t.length; i++) {\n link = createTiddlyLink(popup, t[i].tiddler, false);\n link.appendChild(document.createTextNode(t[i].tiddler));\n }\n}\n//}}}\n\n//{{{\nfunction calendarMaxDays(year, mon)\n{\n var max = config.macros.calendar.monthdays[mon];\n if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {\n max++;\n }\n return max;\n}\n//}}}\n\n//{{{\nfunction createCalendarDayRows(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n\n var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\n if(first1 < 0) first1 = first1 + 7;\n var day1 = -first1 + 1;\n var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\n if(first2 < 0) first2 = first2 + 7;\n var day2 = -first2 + 1;\n var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\n if(first3 < 0) first3 = first3 + 7;\n var day3 = -first3 + 1;\n\n var max1 = calendarMaxDays(year, mon);\n var max2 = calendarMaxDays(year, mon+1);\n var max3 = calendarMaxDays(year, mon+2);\n\n while(day1 <= max1 || day2 <= max2 || day3 <= max3) {\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;\n createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;\n createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;\n }\n}\n//}}}\n\n//{{{\nfunction createCalendarDayRowsSingle(cal, year, mon)\n{\n var row = createTiddlyElement(cal, "tr", null, null, null);\n\n var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);\n if(first1 < 0) first1 = first1+ 7;\n var day1 = -first1 + 1;\n var max1 = calendarMaxDays(year, mon);\n\n while(day1 <= max1) {\n row = createTiddlyElement(cal, "tr", null, null, null);\n createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;\n }\n}\n//}}}\n\n// //ELS 2005.10.30: added styles\n//{{{\nsetStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");\n//}}}\n
// // override cookie settings for CalendarPlugin:\n//{{{\nconfig.options.txtCalFirstDay=6;\nconfig.options.txtCalStartOfWeekend=5;\n//}}}
/***\n|''Name:''|CheckboxPlugin|\n|''Source:''|http://www.TiddlyTools.com/#CheckboxPlugin|\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\nAdd checkboxes to your tiddler content. Checkbox states can be preserved in the document by either automatically modifying the tiddler content or setting/removing tags on specified tiddlers, or they may be saved as local cookies by assigning an optional 'chkID' to the checkbox. Add custom javascript for programmatic initialization and onClick handling for any checkbox. Also provides access to checkbox DOM element data and tracks the checkbox state in TiddlyWiki's config.options[] internal data.\n\n!!!!!Usage\n<<<\nThe checkbox syntax, including all optional parameters, is contained inside a matched set of [ and ] brackets.\n{{{ [x=id(title|tag){init_script}{onclick_script}] }}}\n\nAn alternative syntax lets you place the optional parameters ''outside'' the [ and ] brackets, and is provided for backward-compatibility with existing content that may include checkbox definitions based on earlier releases of this plugin:\n{{{ [x]=id(title|tag){init_script}{onclick_script} }}}\n\n//{{{\n[ ]or[_] and [x]or[X]\n//}}}\nSimple checkboxes. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets\n//{{{\n[x=id]\n//}}}\nAssign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.\n//{{{\n[x(title|tag)] or [x(title:tag)]\n//}}}\nInitializes and tracks the current checkbox state by setting or removing ("TogglyTagging") a particular tag value from a specified tiddler. If you omit the tiddler title (and the | or : separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title|)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to //unselected//. When the checkbox is subsequently changed to //selected//, it will automatically (and silently) create the missing tiddler and then add the tag to it. //''NOTE: beginning with version 2.1.2 of this plugin, the "|" separator is the preferred separator between the title and tag name, as it avoids syntactic ambiguity when ":" is used within tiddler titles or tag names.''//\n//{{{\n[x{javascript}{javascript}]\n//}}}\nYou can define optional javascript code segments to add custom initialization and/or 'onClick' handling to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to the default context-object, 'this'.\n\nThe first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, so that you can perform programmed responses or intercept and override the checkbox state based on complex logic using the TW core API or custom functions defined in plugins (e.g. testing a particular tiddler title to see if certain tags are set or setting some tags when the checkbox is clicked).\n\nNote: if you want to use the default checkbox initialization processing with a custom onclick function, use this syntax: {{{ [x=id{}{javascript}] }}} \n<<<\n!!!!!Configuration\n<<<\nNormally, when a checkbox state is changed, the affected tiddlers are automatically re-rendered, so that any checkbox-dependent dynamic content can be updated. There are three possible tiddlers to be re-rendered, depending upon where the checkbox is placed, and what kind of storage method it is using.\n*''container'': the tiddler in which the checkbox is displayed. (e.g., this tiddler)\n*''tagged'': the tiddler that is being tagged (e.g., "~MyTask" when tagging "~MyTask:done")\n*''tagging'': the "tag tiddler" (e.g., "~done" when tagging "~MyTask:done")\nYou can set the default refresh handling for all checkboxes in your document by using the following javascript syntax either in a systemConfig plugin, or as an inline script. (Substitute true/false values as desired):\n{{{config.checkbox.refresh = { tagged:true, tagging:true, container:true };}}}\n\nYou can also override these defaults for any given checkbox by using an initialization function to set one or more of the refresh options. For example:\n{{{[_{this.refresh.container=false}]}}}\n<<<\n!!!!!Examples\n<<<\n//{{{\n[X] label\n[_] label\n//}}}\n>checked and unchecked static default values\n>[X] label\n>[_] label\n//{{{\n[_=demo] label\n//}}}\n>document-based value (id='demo', no cookie)\n>[_=demo] label\n//{{{\n[_=chkDemo] label\n//}}}\n>cookie-based value (id='chkDemo')\n>[_=chkDemo] label\n//{{{\n[_(CheckboxPlugin|demotag)]\n[_(CheckboxPlugin|demotag){this.refresh.tagged=this.refresh.container=false}]\n//}}}\n>tag-based value (TogglyTagging)\n>[_(CheckboxPlugin|demotag)] toggle 'demotag' (and refresh tiddler display)\n>[_(CheckboxPlugin|demotag){this.refresh.tagged=this.refresh.container=false}] toggle 'demotag' (no refresh)\n>current tags: <script>return store.getTiddler(story.findContainingTiddler(place).id.substr(7)).tags.toString();</script>\n><script label="click to view current tags">alert(store.getTiddler(story.findContainingTiddler(place).id.substr(7)).tags.toString());return false</script>\n//{{{\n[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\n//}}}\n>custom init and onClick functions\n>[X{this.checked=true}{alert(this.checked?"on":"off")}] message box with checkbox state\nRetrieving option values:\nconfig.options['demo']=<script>return config.options['demo']?"true":"false";</script>\nconfig.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>\n\n!!!!!Installation\nimport (or copy/paste) the following tiddlers into your document:\n''CheckboxPlugin'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n2006.05.04 - 2.1.3 fix use of findContainingTiddler() to check for a non-null return value, so that checkboxes won't crash when used outside of tiddler display context (such as in header, sidebar or mainmenu)\n2006.03.11 - 2.1.2 added "|" as delimiter to tag-based storage syntax (e.g. "tiddler|tag") to avoid parsing ambiguity when tiddler titles or tag names contain ":". Using ":" as a delimiter is still supported but is deprecated in favor of the new "|" usage. Based on a problem reported by JeffMason.\n2006.02.25 - 2.1.0 added configuration options to enable/disable forced refresh of tiddlers when toggling tags\n2006.02.23 - 2.0.4 when toggling tags, force refresh of the tiddler containing the checkbox.\n2006.02.23 - 2.0.3 when toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.\n2006.02.23 - 2.0.2 when using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:\n{{{[x([[Tiddler with spaces]]:[[tag with spaces]])]}}}\n2006.01.10 - 2.0.1 when toggling tags, force refresh of the 'tagging tiddler'. For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.\n2006.01.04 - 2.0.0 update for ~TW2.0\n2005.12.27 - 1.1.2 Fix lookAhead regExp handling for {{{[x=id]}}}, which had been including the "]" in the extracted ID. \nAdded check for "chk" prefix on ID before calling saveOptionCookie()\n2005.12.26 - 1.1.2 Corrected use of toUpperCase() in tiddler re-write code when comparing {{{[X]}}} in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.\n2005.12.26 - 1.1.0 Revise syntax so all optional parameters are included INSIDE the [ and ] brackets. Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin. Based on a suggestion by GeoffSlocock\n2005.12.25 - 1.0.0 added support for tracking checkbox state using tags ("TogglyTagging")\nRevised version number for official post-beta release.\n2005.12.08 - 0.9.3 support separate 'init' and 'onclick' function definitions.\n2005.12.08 - 0.9.2 clean up lookahead pattern\n2005.12.07 - 0.9.1 only update tiddler source content if checkbox state is actually different. Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)\n2005.12.07 - 0.9.0 initial BETA release\n<<<\n!!!!!Credits\n<<<\nThis feature was created by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.CheckboxPlugin = {major: 2, minor: 1, revision:3 , date: new Date(2006,5,4)};\n//}}}\n\n// // 1.2.x compatibility\n//{{{\nif (!window.story) window.story=window;\nif (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}\nif (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}\nif (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}\n//}}}\n\n//{{{\nconfig.checkbox = { refresh: { tagged:true, tagging:true, container:true } };\nconfig.formatters.push( {\n name: "checkbox",\n match: "\s\s[[xX_ ][\s\s]\s\s=\s\s(\s\s{]",\n lookahead: "\s\s[([xX_ ])(\s\s])?(=[^\s\ss\s\s(\s\s]{]+)?(\s\s([^\s\s)]*\s\s))?({[^}]*})?({[^}]*})?(\s\s])?",\n handler: function(w)\n {\n var lookaheadRegExp = new RegExp(this.lookahead,"mg");\n lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart)\n {\n // get params\n var checked=lookaheadMatch[1];\n var id=lookaheadMatch[3];\n var tag=lookaheadMatch[4];\n var fn_init=lookaheadMatch[5];\n var fn_click=lookaheadMatch[6];\n // create checkbox element\n var c = document.createElement("input");\n c.setAttribute("type","checkbox");\n c.onclick=onClickCheckbox;\n c.srcpos=w.matchStart+1; // remember location of "X"\n c.container=story.findContainingTiddler(w.output); if (c.container) c.container=c.container.id.substr(7); // tiddler containing checkbox\n c.refresh = { };\n c.refresh.container=config.checkbox.refresh.container;\n c.refresh.tagged=config.checkbox.refresh.tagged;\n c.refresh.tagging=config.checkbox.refresh.tagging;\n w.output.appendChild(c);\n // set default state\n c.checked=(checked.toUpperCase()=="X");\n // get/set state by ID\n if (id) {\n c.id=id.substr(1); // trim off leading "="\n if (config.options[c.id]!=undefined)\n c.checked=config.options[c.id];\n else\n config.options[c.id]=c.checked;\n }\n // get/set state by tag\n if (tag) {\n c.tiddler=c.container;\n c.tag=tag.substr(1,tag.length-2).trim(); // trim off parentheses\n var pos=c.tag.indexOf("|"); if (pos==-1) var pos=c.tag.indexOf(":");\n if (pos==0) { c.tag=tag.substr(1); }\n if (pos>0) { c.tiddler=c.tag.substr(0,pos).replace(/\s[\s[/g,"").replace(/\s]\s]/g,""); c.tag=c.tag.substr(pos+1); }\n c.tag.replace(/\s[\s[/g,"").replace(/\s]\s]/g,"");\n if (!c.tag.length) c.tag="checked";\n var t=store.getTiddler(c.tiddler);\n c.checked = (t && t.tags)?(t.tags.find(c.tag)!=null):false;\n }\n if (fn_init) c.fn_init=fn_init.trim().substr(1,fn_init.length-2); // trim off surrounding { and } delimiters\n if (fn_click) c.fn_click=fn_click.trim().substr(1,fn_click.length-2);\n c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie\n w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;\n }\n }\n }\n)\n//}}}\n\n//{{{\nfunction onClickCheckbox()\n{\n if (this.fn_init)\n // custom function hook to set initial state (run only once)\n { try { eval(this.fn_init); this.fn_init=null; } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }\n else if (this.fn_click)\n // custom function hook to override or react to changes in checkbox state\n { try { eval(this.fn_click) } catch(e) { displayMessage("Checkbox click error: "+e.toString()); } }\n if (this.id)\n // save state in config AND cookie (only when ID starts with 'chk')\n { config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }\n if ((!this.id || this.id.substr(0,3)!="chk") && !this.tag) {\n // save state in tiddler content only if not using cookie or tag tracking\n var t=story.findContainingTiddler(this); if (t) {\n var t=store.getTiddler(t.id.substr(7));\n if (this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed\n t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);\n store.setDirty(true);\n }\n }\n }\n if (this.tag) {\n var t=store.getTiddler(this.tiddler);\n if (!t) { t=(new Tiddler()); t.set(this.tiddler,"",config.options.txtUserName,(new Date()),null); store.addTiddler(t); } \n var tagged=(t.tags && t.tags.find(this.tag)!=null);\n if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }\n if (!this.checked && tagged) { t.tags.splice(t.tags.find(this.tag),1); store.setDirty(true); }\n // if tag state has been changed, force a display update\n if (this.checked!=tagged) {\n if (this.refresh.tagged) story.refreshTiddler(this.tiddler,null,true); // the TAGGED tiddler\n if (this.refresh.tagging) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler\n }\n }\n // refresh containing tiddler (but not during initial rendering, or we get an infinite loop!)\n if (!this.init && this.refresh.container && this.container!=this.tiddler)\n story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox\n return true;\n}\n//}}}
<script label="close">\n var panel=place;\n while (panel && panel.className!='sliderPanel' && panel.className!='floatingPanel')\n { panel=panel.parentNode; }\n if (!panel) { alert('not in a slider'); return false; }\n panel.style.display='none';\n var cookie=panel.button.sliderCookie;\n if (cookie && cookie.length) {\n config.options[cookie]=false;\n if (config.options[cookie]!=panel.button.defOpen)\n saveOptionCookie(cookie);\n else { // remove cookie if slider is in default display state\n var ex=new Date(); ex.setTime(ex.getTime()-1000);\n document.cookie = cookie+"=novalue; path=/; expires="+ex.toGMTString();\n }\n }\n return false;\n</script><script>\n place.lastChild.style.fontWeight="normal";\n if (story.findContainingTiddler(place))\n place.lastChild.className="toolbar button";\n else {\n var s=place.lastChild.style\n s.fontSize="90%"; s.float="right";\n }\n</script>
/***\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
// // add TiddlyTools 'brand' to shadow SiteTitle (default for TiddlyTools starter documents)\n//{{{\nconfig.shadowTiddlers.SiteTitle += " {{medium{with [[TiddlyTools |http://www.TiddlyTools.com]] extensions}}}\sn";\n//}}}\n\n// // add shadows for common TiddlyTools default tiddlers used in starter documents\n//{{{\nconfig.shadowTiddlers.Welcome = "[[Welcome]]";\nconfig.shadowTiddlers.About = "[[About]]";\nconfig.shadowTiddlers.Download = "[[Download]]";\nconfig.shadowTiddlers.Contact = "[[Contact]]";\n//}}}\n\n// // add param handler for "hide:elementID"\n//{{{\nif (config.paramifiers)\n config.paramifiers.hide = { onstart: function(id) { var e=document.getElementById(id); if (e) e.style.display="none"; } };\n//}}}\n\n// // add param handler for "show:elementID"\n//{{{\nif (config.paramifiers)\n config.paramifiers.show = { onstart: function(id) { var e=document.getElementById(id); if (e) e.style.display="block"; } };\n//}}}\n\n// // add param handler for "group:tiddlerName"\n//{{{\nif (config.paramifiers)\n config.paramifiers.group = { onstart: function(id) { story.displayTiddlers(null,store.getTiddlerText(id,"").readBracketedList()) } };\n//}}}\n\n// // force no animation\n//{{{\nconfig.options.chkAnimate=false;\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//}}}
// // This HIJACK tweak pre-processes source content to convert "backslash-newline" into {{{<<br>>>}}} before wikify(), so that literal newlines can be embedded in line-mode wiki syntax (e.g., tables, bullets, etc.). Based on a suggestion from Sitaram Chamarty.\n//{{{\nwindow.coreWikify = wikify;\nwindow.wikify = function(source,output,highlightRegExp,tiddler)\n{\n if (source) source=source.replace(/\s\s\sn\ss*/mg,"<<br>>");\n coreWikify(source,output,highlightRegExp,tiddler)\n}\n//}}}\n\n// // This tweak adds a check for any tiddlers that are being actively edited, so that accidental page transitions don't discard tiddler content that has been entered but not yet saved to the 'store' (i.e., by pressing 'done').\n//{{{\nconfig.messages.editing_confirmExit ="There are currently open tiddler editors that may contain unsaved changes.\snIf you continue you will lose those changes";\nfunction confirmExit()\n{\n hadConfirmExit = true;\n if(store && store.isDirty && store.isDirty())\n return config.messages.confirmExit;\n // added by ELS\n var editing=false;\n story.forEachTiddler(function(title,element) { if(element.getAttribute("dirty")=="true") editing=true; });\n if (editing) return config.messages.editing_confirmExit;\n}\n//}}}\n\n// // When a slider is opened/closed with animation enabled, the opacity/alphafilter styles are incrementally adjusted to create a "fade-in/fade-out" effect. However, this effect seems to render incredibly slowly on FireFox, and even slower when the background image is a complex JPG photo image, making animation impractical to use. This tweak disables the opacity/alphafilter handling, while leaving the 'incremental height' animation intact. The resulting increase in performance makes it possible to leave the animation enabled so that you can benefit from the visual cues it provides.\n//{{{\nSlider.prototype.tick = function()\n{\n this.progress += this.step;\n if(this.progress < 0 || this.progress > 1)\n {\n this.stop();\n return false;\n }\n else\n {\n var f = Animator.slowInSlowOut(this.progress);\n var h = this.realHeight * f;\n this.element.style.height = h + "px";\n// REMOVED BY ELS:\n// this.element.style.opacity = f;\n// this.element.style.filter = "alpha(opacity:" + f * 100 +")";\n return true;\n }\n}\n//}}}\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
// // date plugin calendar colors\n//{{{\nconfig.macros.date.holidays=[ "01/01", "07/04", "07/24", "11/24" ]; // NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)\nconfig.macros.date.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\nconfig.macros.date.format="YYYY.0MM.0DD"; // default date display format\nconfig.macros.date.linkformat="YYYY.0MM.0DD"; // 'dated tiddler' link format\nconfig.macros.date.weekendbg="#c0c0c0";\nconfig.macros.date.holidaybg="#ffaace";\nconfig.macros.date.modifiedsbg="#bbeeff";\nconfig.macros.date.linkedbg="#babb1e";\nconfig.macros.date.remindersbg="#c0ffee";\n//}}}\n
HansWobbe
<script>\n if (!story.findContainingTiddler(place)) return;\n var t=story.findContainingTiddler(place); // get the tiddler element\n for (var i=0; i<t.childNodes.length; i++)\n if (hasClass(t.childNodes[i],"viewer")) t.ondblclick=null; // disable double-click\n</script>
<div class='toolbar' macro='toolbar saveTiddler -cancelTiddler copyTiddler deleteTiddler convertToWiki autosizeEditor increaseEditor decreaseEditor resizeEditor'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div>\n<div class='editorFooter'>\n<span macro='message views.editor.tagPrompt'></span>\n<span macro='tagChooser'></span>\n</div>\n<span macro="tiddler SetUserName"></span>
/% usage:\n <<tiddler ExpandSlidersScript with: elementID expandlabel collapselabel>>\n\n%/<script label="expand">\n // if 'in a tiddler', expand all sliders... otherwise, expand based on passed in element ID\n var here=story.findContainingTiddler(place);\n if (!here) {\n if ("$1"=="$"+"1") { alert("ExpandSlidersScript: not in a tiddler, please use 'with: elementID' syntax"); return; }\n var here=document.getElementById("$1");\n if (!here) { alert("ExpandSlidersScript: unknown elementID: '$1'"); return; }\n }\n var expandlabel="expand"; if ("$2"!="$"+"2") var expandlabel="$2";\n var collapselabel="collapse"; if ("$3"!="$"+"3") var collapselabel="$3";\n var elems=here.getElementsByTagName("*");\n var state=(place.innerHTML.toLowerCase().indexOf("expand")!=-1)?"none":"block";\n for (var e=0; e<elems.length; e++) {\n var p=elems[e].sliderPanel;\n if (p && p.className=="sliderPanel") {\n if (p.style.display==state) window.onClickNestedSlider({target:elems[e]});\n }\n }\n place.innerHTML=state=="none"?collapselabel:expandlabel;\n return false;\n</script><script>\n place.lastChild.className="button";\n var expandlabel="expand"; if ("$2"!="$"+"2") var expandlabel="$2";\n var collapselabel="collapse"; if ("$3"!="$"+"3") var collapselabel="$3";\n if (place.lastChild.innerHTML.toLowerCase().indexOf("expand")==-1)\n place.lastChild.innerHTML=collapselabel;\n else\n place.lastChild.innerHTML=expandlabel;\n</script>
<<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
/***\n|''Name:''|ExternalIncludePlugin|\n|''Author:''|Dan Tohatan - DataFix|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0+|\n\nThis plugin allows TransClusion of external content (from HTTP sites).\n\n!!!!!Parameters\n<<<\nFor IncludeExternal macro call:\n# Tiddler name suffix. (E.g. if this parameter is ":TC1" the tiddler containing the transcluded content is called "YourTiddler:TC1", where YourTiddler is the name of your tiddler) (NOTE: Each transcluded content tiddler must have a unique name)\n# URL to grab content from (using HTTP GET)\n# Phrase to look for indicating the start of content (this phrase is included in the content)\n# Phrase to look for indicating the end of content (this phrase is NOT included in the content)\n# Type of content to grab (valid values: "html" or "raw")\n\nFor RefreshExternalInclude macro call:\n# The name of the tiddler to refresh.\n\nNOTE: All transcluded tiddlers are marked with the tag "tccontent".\n<<<\n!!!!!Revision History\n<<<\n2006.11.23 1.0.1 Added refresh functionality.\n2006.11.22 1.0.0 Initial release.\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by Dan Tohatan.\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.externalInclude = {major: 1, minor: 0, revision: 1, date: new Date(2006,11,23)};\n\nfunction transclude(place, title, url, start, end, contentType)\n{\n //create ability to transclude raw wiki markup from another location\n \n try {\n netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");\n } catch (e) {\n }\n var xmlhttp=false;\n /*@cc_on @*/\n /*@if (@_jscript_version >= 5)\n // JScript gives us Conditional compilation, we can cope with old IE versions.\n // and security blocked creation of the objects.\n try {\n xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");\n } catch (e) {\n try {\n xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");\n } catch (E) {\n xmlhttp = false;\n }\n }\n @end @*/\n if (!xmlhttp && typeof XMLHttpRequest!='undefined') {\n try {\n xmlhttp = new XMLHttpRequest();\n } catch (e) {\n xmlhttp=false;\n }\n }\n if (!xmlhttp && window.createRequest) {\n try {\n xmlhttp = window.createRequest();\n } catch (e) {\n xmlhttp=false;\n }\n }\n xmlhttp.open("GET", url, false);\n// xmlhttp.onreadystatechange=function() {\n// if (xmlhttp.readyState==4) {\n//this is where the code used to be\n// }\n// }\n xmlhttp.send(null);\n//and this is where it now resides\n var resp = xmlhttp.responseText.substr(0);\n var startIdx = 0;\n var endIdx = resp.length - 1;\n if(start && start.length > 0)\n {\n startIdx = resp.indexOf(start.replace(/\s\s\s"/g, "\s""));\n }\n if(end && end.length > 0)\n {\n endIdx = resp.indexOf(end.replace(/\s\s\s"/g, "\s""), startIdx + 1);\n }\n var body;\n if(contentType == "html") {\n var text = fixLinks(resp.substring(startIdx, endIdx), "href", url);\n text = fixLinks(text, "src", url);\n var regexp = encodeRE("<a");\n var re = new RegExp(regexp, "gi");\n text = text.replace(re, "<a target=\s"_blank\s"");\n body = "<html><!-- " + url + ";" + start + ";" + end + ";" + contentType + " -->" + text + "</html>";\n }\n else {\n body = "<html><!-- " + url + ";" + start + ";" + end + ";" + contentType + " --></html>" + resp.substring(startIdx, endIdx);\n }\n if(place)\n {\n wikify(body, place, null, null);\n }\n var t = new Tiddler();\n t.set(title, body, config.options.txtUserName, (new Date()), "tccontent", (new Date()));\n store.addTiddler(t);\n store.notify(title, true);\n store.setDirty(true);\n}\n\nfunction encodeRE(s) { return s.replace(/([:.*+?^${}()|[\s]\s/\s\s])/g, '\s\s$1'); }\n\nfunction fixLinks(txt, attrib, fullUrl)\n{\n var rootUrl = getPath(fullUrl);\n var idx = txt.toLowerCase().indexOf(attrib + "=");\n while(idx >= 0)\n {\n idx = idx + attrib.length + 1;\n var endIdx = idx;\n //has quotes\n if(txt.charAt(idx) == '"')\n {\n //find next quote\n idx = idx + 1;\n endIdx = txt.indexOf("\s"", idx);\n }\n //no quotes\n else\n {\n //find first space or '>'\n var spcIdx = txt.indexOf(" ", idx);\n var endTagIdx = txt.indexOf(">", idx);\n endIdx = Math.min(spcIdx, endTagIdx);\n }\n var url = txt.slice(idx, endIdx);\n var oldlen = txt.length;\n if(!(url.slice(0, 5) == "http:") && !(url.slice(0, 5) == "ftp:")\n && !(url.slice(0, 5) == "file:"))\n {\n if(url.charAt(0) == '/')\n {\n url = getHost(rootUrl) + url;\n }\n else if(url.charAt(0) == '#')\n {\n url = fullUrl + url;\n }\n else\n {\n url = rootUrl + "/" + url;\n }\n }\n else\n {\n //replace this root-url with remote root-url\n var exp = encodeRE(getPath(window.location.href));\n var re = new RegExp(exp, "gi");\n url = url.replace(re, rootUrl);\n }\n txt = txt.substring(0, idx) + url + txt.substring(endIdx, txt.length + endIdx);\n idx = txt.toLowerCase().indexOf(attrib + "=", endIdx - oldlen + txt.length);\n }\n return txt;\n}\n\nfunction getPath(url)\n{\n //find index of last '/'\n var idx = -1;\n var vidx = -1;\n do\n {\n vidx = url.indexOf("/", idx + 1);\n if(vidx >= 0)\n {\n idx = vidx;\n }\n } while(vidx >= 0);\n return url.slice(0, idx);\n}\n\nfunction getHost(url)\n{\n //find index of first '/' at index 8 or more\n var idx = url.indexOf("/", 8);\n return url.slice(0, idx);\n}\n\nfunction findTiddlerTitle(p)\n{\n while ( (!p.id || p.id.substr(0,7)!="tiddler")&& p.parentNode )\n p=p.parentNode;\n return (p.id?((p.id.substr(0,7)=="tiddler")?p.id.substr(7):""):"");\n}\n\nfunction refreshTransclusion(tiddler)\n{\n var title = tiddler.title;\n var txt = store.getTiddlerText(title);\n var urlEnd = txt.indexOf(";", 11);\n var url = txt.substring(11, urlEnd);\n var startEnd = txt.indexOf(";", urlEnd + 1);\n var start = txt.substring(urlEnd + 1, startEnd);\n var endEnd = txt.indexOf(";", startEnd + 1);\n var end = txt.substring(startEnd + 1, endEnd);\n var typeEnd = txt.indexOf(" -->", endEnd + 1);\n var type = txt.substring(endEnd + 1, typeEnd);\n if(start == "undefined")\n start = null;\n if(end == "undefined")\n end = null;\n store.deleteTiddler(title);\n transclude(null, title, url, start, end, type);\n}\n\nconfig.macros.IncludeExternal = { };\n\nconfig.macros.IncludeExternal.handler = function(place,macroName,params)\n{\n var tidTitle = findTiddlerTitle(place) + params[0];\n if (!store.fetchTiddler(tidTitle)) {\n transclude(place, tidTitle, params[1], params[2], params[3], params[4]);\n }\n else {\n wikify(store.getTiddlerText(tidTitle), place, null, null);\n }\n}\n\nconfig.macros.RefreshExternalInclude={\n handler: function(place,macroName,params,wikifier,paramString,tiddler) {\n if (!tiddler) { // fallback... find tiddler if none provided\n var tid=story.findContainingTiddler(place);\n if (!tid) return; // not in a tiddler, do nothing\n var tiddler=store.getTiddler(tid.getAttribute('tiddler'));\n }\n var tid=params[0]; if (!tid) tid=tiddler.title;\n var btn=createTiddlyButton(place,'Refresh','Refresh Transclusion: '+tid,this.onclick);\n btn.setAttribute('which',tid);\n btn.setAttribute('whatParent', findTiddlerTitle(place));\n },\n onclick: function(e) {\n store.deleteTiddler(this.getAttribute('which'));\n story.refreshTiddler(this.getAttribute('whatParent'),1,true);\n }\n}\n\nconfig.macros.RefreshAllTransclusions={\n handler: function(place,macroName,params,wikifier,paramString) {\n var btn=createTiddlyButton(place,'Refresh All','Refresh All Transclusions',this.onclick);\n },\n onclick: function(e) {\n alert("Will now refresh all tiddlers containing transcluded content. Press OK and be patient.");\n var tiddlers = store.reverseLookup("tags","tccontent",true);\n for(var i = 0; i < tiddlers.length; i++)\n {\n refreshTransclusion(tiddlers[i]);\n }\n }\n}\n\n//}}}
__''Configure this [[TiddlyTools|http://www.TiddlyTools.com/]] 'starter' document:''__\nThese settings allow you to quickly configure various optional features, behaviors, and appearance of your document. Once you have set these options, you can apply further customizations by directly editing the relevant configuration tiddlers or by creating/importing tiddlers containing additional plugins, scripts, styles, templates, etc.\n++++!!!{{big{[1: username]}}}>\nYour current username is: <<option txtUserName>><script>\n place.lastChild.style.fontSize="8pt"; place.lastChild.style.width="20em";\n</script>\n* ''Your username is stored in your web browser as a //private// cookie'', and can only be accessed by this document. Note: all locally-stored TiddlyWiki documents (i.e., ''file:...'') are considered part of the same domain, and share a single set of cookie values.\n* ''Your username is recorded as the last modifier ("author") of any tiddlers you have changed'', and can be shown alongside the tiddler title and creation/modification dates that appear above each displayed tiddler.\n* To reduce 'information clutter', ''~TiddlyTools does //not// automatically display the modifier information.'' You can enable this feature by editing the ~TiddlyTools ViewTemplate to remove the ~HTML-style comments that surround the modifier display syntax:\n{{{\n<!--<span macro='view modifier link'></span>, -->\n}}}\n===\n+++!!!{{big{[2: menus]}}}>\nBy default, ''new ~TiddlyTools 'starter' documents include a complete set of ~TiddlyTools enhanced menus'', along with the necessary plugins/scripts/styles to support those features. These enhancements provide a wide range of extended editing and authoring features for you to use, "right out of the box". ''If you do not want or need all of these features, you can quickly select and install a simplified set of menu definitions'' from the choices below:\n\nselect a menu level:<<br>>{{medium{<<tiddler SwitchMenus>>}}}\n* ''Full'' - (default) includes all ~TiddlyTools enhanced menu features\n* ''Lite'' - minus: attach, export, single-page/open at top (options), calendar, listbox tab (contents), installed plugins summary (main menu), all extras (except for ~TagCloud).\n* ''Mini'' - same as ~TiddlyTools Lite menus, minus: download, contact, recent changes, tiddler groups, yesterday/today/tommorrow (recent), upload/save to web, toggle titles/menubar, create xml/rss file (saving), all extras (including ~TagCloud)\nWarning - Changing menus levels will overwrite the content of the following 'menu definition' tiddlers:\n>MainMenu, SideBarOptions, SideBarTabs, StoryMenu, SiteMenu, SiteMenuGoto, SiteMenuFile, SiteMenuOptions, SiteMenuExtras\nYou can edit these tiddlers at any time and customize them to suit your needs; however, ''any customizations or changes that have been made to these tiddlers will be discarded whenever you select a TiddlyTools menu level.''\n>hint:After you have selected an appropriate menu level, you can reduce your document size by removing the sets of tiddlers that define the different menu alternatives (i.e., all tiddlers tagged with <<tag full>>/<<tag lite>>/<<tag mini>>). This also 'locks in' your current menu level, so that you cannot switch menu levels for this document again. Of course, you can always edit the currently installed menu definition tiddlers in the normal ~TiddlyWiki manner, allowing you to make any modifications to the menus that you wish by using copy/paste, ImportTiddlersPlugin or simply typing additions and corrections directly into the tiddler content.\n===\n+++!!!{{big{[3: packages]}}}><<tiddler ImportPackages>>===\n+++!!!{{big{[4: configuration]}}}>\nSome tiddlers define settings or functions that control various ~TiddlyWiki behaviors. You can customize some of these core and plugin configuration options by editing the following tiddlers:\n* TiddlerGroupsList\n* AttachFileServerScripts\n* CalendarPluginConfig\n* DatePluginConfig\n* ConfigTweaks\n===\n+++!!!{{big{[5: content]}}}>\nTo begin entering and formatting your content, you'll probably want to create/modify the following tiddlers:\n* DefaultTiddlers\n* SiteTitle\n* SiteSubtitle\n* [[Welcome]]\n* [[About]]\n* [[Download]]\n* [[Contact]]\n* LegalStatements\n===
/***\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:''|HTMLFormattingPlugin|\n|''Source:''|http://www.TiddlyTools.com/#HTMLFormattingPlugin|\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\nThe shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.\n\nWhen HTML formatting syntax is embedded within a tiddler (in between {{{<}}}{{{html>}}} and {{{<}}}{{{/html>}}} markers) TiddlyWiki passes this content to the browser for processing as 'native' HTML. However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain. This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.\n!!!!!Usage\n<<<\nThe ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.\n\nWhen a tiddler is about to be displayed, ~TiddlyWiki looks for tiddler content contained within ''<{{{html}}}>'' and ''<{{{/html}}}>'' HTML tags. This content (if any) is passed directly to the browser's internal "rendering engine" to process as ~HTML-formatted content. Once the HTML formatting has been processed, all the pieces of text occuring in between the HTML formatting are then processed by the ~TiddlyWiki rendering engine, one piece at a time, so that normal wiki-style formatting can be applied to the individual text pieces.\n<<<\n!!!!!Line breaks\n<<<\nOne major difference between Wiki formatting and HTML formatting is how "line breaks" are processed. Wiki formatting treats all line breaks as literal content to be displayed //as-is//. However, because HTML normally ignores line breaks and actually processes them as simple "word separators" instead, many people who write HTML include extra line breaks in their documents, just to make the "source code" easier to read.\n\nEven though you can use HTML tags within your tiddler content, the default treatment for line breaks still follows the Wiki-style rule (i.e., all new lines are displayed as-is). When adding HTML content to a tiddler (especially if you cut-and-paste it from another web page), you should take care to avoid adding extra line breaks to the text.\n\nIf removing all the extra line breaks from your HTML content would be a big hassle, you can quickly //override the default Wiki-style line break rule// so that the line breaks use the standard HTML rules instead. Placing a ''<{{{hide linebreaks}}}>'' tag within the tiddler's HTML content changes all line breaks to spaces before rendering the content, so that the literal line breaks will be processed as simple word-breaks instead.\n\nNote: this does //not// alter the actual tiddler content that is stored in the document, just the manner in which it is displayed. Any line breaks contained in the tiddler will still be there when you edit its content. Also, to include a literal line break when the ''<{{{hide linebreaks}}}>'' tag is present, you will need to use a ''<{{{br}}}>'' or ''<{{{p}}}>'' HTML tag instead of simply typing a line break.\n<<<\n!!!!!How it works\n<<<\nThe TW core support for HTML does not let you put ANY wiki-style syntax (including TW macros) *inside* the {{{<html>...</html>}}} block. Everything between {{{<html>}}} and {{{</html>}}} is handed to the browser for processing and that is it. Fortunately, this plugin ADDS the ability to let you put wiki-syntax (including macros) inside the html. It does this by first giving the tiddler source content to the browser to process the HTML, and then handling any wiki-based syntax that remains afterward.\n\nHowever, not all wiki syntax can be safely passed through the browser's parser. Specifically, any TW macros inside the HTML will get 'eaten' by the browser since the macro brackets, {{{<<...>>}}} use the "<" and ">" that normally delimit the HTML/XML syntax recognized by the browser's parser.\n\nSimilarly, you can't use InlineJavascript within the HTML because the {{{<script>...</script>}}} syntax will also be consumed by the browser and there will be nothing left to process afterward. Note: unfortunately, even though the browser removes the {{{<script>...</script>}}} sequence, it doesn't actually execute the embedded javascript code that it removes, so any scripts contained inside of <html> blocks in TW are currently being ignored. :-(\n\nAs a work-around to allow TW *macros* (but not inline scripts) to exist inside of <html> formatted blocks of content, the plugin first converts the {{{<<}}} and {{{>>}}} into "%%(" and ")%%", making them "indigestible" so they can pass unchanged through the belly of the beast (the browser's HTML parser).\n\nAfter the browser has done its job, the wiki syntax sequences (including the "undigested" macros) are contained in #text nodes in the browser-generated DOM elements. The plugin then recursively locates and processes each #text node, converts the %%( and )%% back into {{{<<}}} and {{{>>}}}, passes the result to wikify() for further rendering of the wiki-formatted syntax into a containing SPAN that replaces the previous #text node. At the end of this process, none of the encoded %%( and )%% sequences remain in the rendered tiddler output.\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''HTMLFormattingPlugin'' (tagged with <<tag systemConfig>>)\n^^documentation and javascript for HTMLFormatting handling^^\n<<<\n!!!!!Revision History\n<<<\n''2006.09.10 [2.1.4]'' update formatter for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)\n''2006.05.28 [2.1.3]'' in wikifyTextNodes(), decode the *value* of TEXTAREA nodes, but don't wikify() its children. (thanks to "ayj" for bug report)\n''2006.02.19 [2.1.2]'' in wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content. This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)\n''2006.02.05 [2.1.1]'' wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2005.12.01 [2.1.0]'' don't wikify #TEXT nodes inside SELECT and TEXTAREA elements\n''2005.11.06 [2.0.1]'' code cleanup\n''2005.10.31 [2.0.0]'' replaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code\n''2005.10.09 [1.0.2]'' combined documentation and code into a single tiddler\n''2005.08.05 [1.0.1]'' moved HTML and CSS definitions into plugin code instead of using separate tiddlers\n''2005.07.26 [1.0.1]'' Re-released as a plugin. Added <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling\n''2005.07.20 [1.0.0]'' Initial Release (as code adaptation)\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.HTMLFormatting = {major: 2, minor: 1, revision: 4, date: new Date(2006,9,10)};\n\n// find the formatter for HTML and replace the handler\ninitHTMLFormatter();\nfunction initHTMLFormatter()\n{\n for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);\n if (i<config.formatters.length) config.formatters[i].handler=function(w) {\n if (!this.lookaheadRegExp) // fixup for TW2.0.x\n this.lookaheadRegExp = new RegExp(this.lookahead,"mg");\n this.lookaheadRegExp.lastIndex = w.matchStart;\n var lookaheadMatch = this.lookaheadRegExp.exec(w.source)\n if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {\n var html=lookaheadMatch[1];\n // optionally suppress wiki-style literal handling of newlines\n // strip any carriage returns added by Internet Explorer's textarea edit field\n // encode newlines as \sn so Internet Explorer's HTML parser won't eat them\n // encode macro brackets (<< and >>) so HTML parser won't eat them\n if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(regexpNewLine,' ');\n html=html.replace(regexpCarriageReturn,'');\n html=html.replace(regexpNewLine,'\s\sn');\n html=html.replace(/<</g,'%%(').replace(/>>/g,')%%');\n // create span to hold HTML\n // parse HTML and normalize the results\n // walk node tree and call wikify() on each text node\n var e = createTiddlyElement(w.output,"span");\n e.innerHTML=html;\n e.normalize(); \n wikifyTextNodes(e);\n // advance to next parse position\n w.nextMatch = this.lookaheadRegExp.lastIndex;\n }\n }\n}\n\n// wikify text nodes remaining after HTML content is processed (pre-order recursion)\nfunction wikifyTextNodes(theNode)\n{\n // textarea node doesn't get wikified, just decoded... \n if (theNode.nodeName.toLowerCase()=='textarea')\n theNode.value=theNode.value.replace(/\s%%\s(/g,'<<').replace(/\s)\s%%/g,'>>').replace(regexpBackSlashEn,'\sn');\n else for (var i=0;i<theNode.childNodes.length;i++) {\n var theChild=theNode.childNodes.item(i);\n if (theChild.nodeName.toLowerCase()=='option') continue;\n if (theChild.nodeName.toLowerCase()=='select') continue;\n wikifyTextNodes(theChild);\n if (theChild.nodeName=='#text') {\n var txt=theChild.nodeValue;\n // decode macro brackets and newlines\n txt=txt.replace(/\s%%\s(/g,'<<').replace(/\s)\s%%/g,'>>').replace(regexpBackSlashEn,'\sn');\n // replace text node with wikified() span\n var newNode=createTiddlyElement(null,"span");\n theNode.replaceChild(newNode,theChild);\n wikify(txt,newNode);\n }\n }\n}\n//}}}
/***\n|''Name:''|HTMLToWikiPlugin|\n|''Author:''|Dan Tohatan - DataFix|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0+|\n\nThis plugin converts HTML code to Wiki markup.\n\n!!!!!Configuration\n<<<\nNone\n<<<\n!!!!!Revision History\n<<<\n2006.11.08 1.0.3 Renamed to HTMLToWiki (old name: WikifierPlugin).\n2006.10.27 1.0.2 Added support for headings, blockquotes, super/sub-script, strikethrough, and highlights (with CSS!).\n2006.10.26 1.0.1 Now parses HTML as opposed to XHTML.\n2006.10.24 1.0.0 Initial release.\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by Dan Tohatan.\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.convertToWiki = {major: 1, minor: 0, revision: 3, date: new Date(2006,11,8)};\n\nfunction htmlToWiki(code)\n{\n var x = toDOM(code);\n if(x)\n {\n var outStr = parseRecursive(x, "");\n return outStr;\n }\n else\n {\n return "Parse failed. Make sure you entered valid HTML.\sn" + outStr;\n }\n}\n\nfunction toDOM(HTMLstring)\n{\n var d = document.createElement('div');\n d.innerHTML = HTMLstring;\n var docFrag = document.createDocumentFragment();\n\n while (d.firstChild) {\n docFrag.appendChild(d.firstChild)\n };\n\n return docFrag;\n}\n\nfunction htmlify(str)\n{\n //fix a key difference between Firefox and IE\n return str.replace(/\sn/g, "").replace(/\st+/g, " ").replace(/\ss+/g, " ");\n}\n\nfunction trim(str)\n{\n return str.replace(/^\ss*|\ss*$/g,"");\n}\n\nfunction parseRecursive(x, inStr)\n{\n var outStr = inStr;\n outStr = outStr + startTag(x.nodeName.toLowerCase(), x);\n for(var i = 0; i < x.childNodes.length; i++)\n {\n if(x.childNodes[i].nodeName == "#text")\n {\n var textNode = x.childNodes[i];\n if(textNode && textNode.nodeValue)\n {\n //clear whitespace\n var value = htmlify(textNode.nodeValue);\n if(value.length > 0)\n {\n outStr = outStr + value;\n }\n }\n }\n else\n {\n outStr = parseRecursive(x.childNodes[i], outStr);\n }\n }\n outStr = outStr + endTag(x.nodeName.toLowerCase(), x);\n return outStr;\n}\n\nfunction getPrevSibling(node)\n{\n var parent = node.parentNode;\n if(parent)\n {\n for(var i = 0; i < parent.childNodes.length; i++)\n {\n if(parent.childNodes[i] == node && i > 0)\n {\n return parent.childNodes[i-1];\n }\n }\n }\n return null;\n}\n\nfunction getNextSibling(node)\n{\n var parent = node.parentNode;\n if(parent)\n {\n for(var i = 0; i < parent.childNodes.length; i++)\n {\n if(parent.childNodes[i] == node && i < parent.childNodes.length - 1)\n {\n return parent.childNodes[i+1];\n }\n }\n }\n return null;\n}\n\nfunction getAttributeValue(node, attrib)\n{\n for(var i = 0; i < node.attributes.length; i++)\n {\n if(node.attributes[i].nodeType == 2)\n {\n if(node.attributes[i].nodeName.toLowerCase() == attrib)\n {\n return node.attributes[i].nodeValue;\n }\n }\n }\n return "";\n}\n\nfunction startTag(tag, node)\n{\n var parent = "";\n if(node.parentNode)\n parent = node.parentNode.nodeName.toLowerCase();\n switch(tag)\n {\n case "b":\n case "strong":\n return "''";\n case "i":\n case "em":\n return "//";\n case "u":\n return "__";\n case "a":\n return "[[";\n case "img":\n // syntax is [img[Alt Text|SRC]]\n if(getAttributeValue(node, "align").toLowerCase() == "right")\n {\n return "[>img[";\n }\n return "[img[";\n case "p":\n return "\sn\sn";\n case "li":\n {\n var listChar = "*";\n if(parent == "ol")\n {\n listChar = "#";\n }\n var count = 0;\n var retVal = listChar;\n var current = node.parentNode;\n while(current && (current.nodeName.toLowerCase() == "ul" ||\n current.nodeName.toLowerCase() == "ol" ||\n current.nodeName.toLowerCase() == "li"))\n {\n if(current.nodeName.toLowerCase() != "li")\n {\n count++;\n if(count > 1)\n {\n retVal = retVal + listChar;\n }\n }\n current = current.parentNode;\n }\n retVal = "\sn" + retVal;\n return retVal;\n }\n case "ul":\n case "ol":\n return "";\n case "td":\n return "|";\n case "table":\n return "\sn";\n case "h1":\n return "!";\n case "h2":\n return "!!";\n case "h3":\n return "!!!";\n case "h4":\n return "!!!!";\n case "h5":\n return "!!!!!";\n case "h6":\n return "!!!!!!";\n case "s":\n return "--";\n case "sup":\n return "^^";\n case "sub":\n return "~~";\n case "blockquote":\n return "\sn<<<\sn";\n case "span":\n {\n var retVal = "@@" + node.style.cssText.toLowerCase();\n if(node.style.cssText.charAt(node.style.cssText.length - 1) != ';')\n {\n retVal = retVal + ";";\n }\n return retVal;\n }\n }\n return "";\n}\n\nfunction endTag(tag, node)\n{\n var nextSibling = getNextSibling(node);\n var prevSibling = getPrevSibling(node);\n switch(tag)\n {\n case "a":\n return "|" + getAttributeValue(node, "href") + "]]";\n case "span":\n return "@@";\n case "h1":\n case "h2":\n case "h3":\n case "h4":\n case "h5":\n case "h6":\n return "\sn";\n case "img":\n {\n // syntax is [img[Alt Text|SRC]]\n var retVal = "";\n if(getAttributeValue(node, "alt") != "")\n {\n retVal = retVal + getAttributeValue(node, "alt") + "|"; \n }\n retVal = retVal + getAttributeValue(node, "src") + "]]";\n return retVal;\n }\n case "br":\n return "\sn";\n case "p":\n return "";\n case "ul":\n case "ol":\n if(nextSibling && nextSibling.nodeName.toLowerCase() != "li"\n && nextSibling.nodeName.toLowerCase() != "ul"\n && nextSibling.nodeName.toLowerCase() != "ol"\n && (nextSibling.nodeName.toLowerCase() != "#text" ||\n trim(htmlify(nextSibling.nodeValue)).length > 0))\n return "\sn";\n return "";\n case "hr":\n {\n var retVal = "----\sn";\n if(prevSibling && prevSibling.nodeName == "#text")\n {\n return "\sn" + retVal;\n }\n return retVal;\n }\n case "li":\n return "";\n case "tr":\n return "|\sn";\n case "td":\n case "table":\n return "";\n }\n //usually identical to start tag.\n // if not, add special cases here\n return startTag(tag, node);\n}\n\nconfig.commands.convertToWiki = {\n text: 'html-to-wiki',\n tooltip: 'convert html markup to wiki markup',\n hideReadOnly: true,\n handler: function(event,src,title) {\n var here=story.findContainingTiddler(src); if (!here) return;\n var ta=here.getElementsByTagName('textarea'); if (!ta) return;\n ta[0].value = htmlToWiki(ta[0].value);\n return false;\n }\n};\n\nconfig.shadowTiddlers.EditTemplate = config.shadowTiddlers.EditTemplate.replace("deleteTiddler", "deleteTiddler convertToWiki");\n\n//}}}
'HansWobbe' is just an initial starting point.\n\n!!! Nov. 23, 2006 Note: See TransClusionTest\n\n''//See my comments in italics -- Dan//''\n\nDan:\n\nI am working in this file in an attempt to gain an adequate appreciation of what you have created.\n\nI have a few questions and requests...\n* Requests:\n** Please create the simplest possible "Hello, world" macro for me.\n*** //Here you go: ''<<helloworld>>'' (edit this tiddler to see the macro being called)//\n* Questions:\n** Why did you switch from XHTML to HTML?\n*** //Before I discovered the HTML DOM parser, I initially used an XML parser which required the input to be valid XHTML.//\n** Did you add the "autosize" to the edit menu, or is that a new feature that Eric added to his version?\n*** //The "autosize" is one of Eric's features.//\n\n----\n<html>\n<p> This is an HTML paragraph. </p>\n</html>\n\n----\nWikifierPlugin\n* this may need to be renamed if we wish to release it more broadly since the core TiddlyWiki system already uses 'wikifier'.\n** //I have renamed it to HTMLToWikiPlugin.//
/***\n|''Name:''|HelloWorldMacro|\n|''Author:''|Dan Tohatan|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0.10|\n\nThis plugin displays "Hello world."\n\n!!!!!Usage\n<<<\nWhen installed, this plugin defines a macro: {{{<<helloworld>>}}}.\n<<<\n!!!!!Installation\n<<<\nimport (or copy/paste) the following tiddlers into your document:\n''HelloWorldMacro'' (tagged with <<tag systemConfig>>)\n<<<\n!!!!!Revision History\n<<<\n''2006.11.08 [1.0.0]'' Initial release\n<<<\n!!!!!Code\n***/\n//{{{\nversion.extensions.helloworld = {major: 1, minor: 0, revision: 0, date: new Date(2006,11,8)};\n\nconfig.macros.helloworld = { };\n\nconfig.macros.helloworld.handler = function(place,macroName,params)\n{\n wikify("Hello world", place, null, null);\n}\n//}}}
<script>\n var s=place.parentNode.style;\n s.backgroundImage="none";\n s.backgroundColor="transparent"\n s.borderColor="transparent";\n s.borderWidth=0;\n s.margin=0;\n s.padding=0;\n</script>
<script>\n // get the tiddler element\n var t=story.findContainingTiddler(place);\n if (t && t.id!="tiddlerHideTiddlerSubtitle") \n for (var i=0; i<t.childNodes.length; i++)\n if (hasClass(t.childNodes[i],"subtitle"))\n t.childNodes[i].style.display="none";\n</script>
<script>\n var t=story.findContainingTiddler(place);\n if (t && t.id!="tiddlerHideTiddlerTags")\n for (var i=0; i<t.childNodes.length; i++)\n if (hasClass(t.childNodes[i],"tagging")||hasClass(t.childNodes[i],"tagged"))\n t.childNodes[i].style.display="none";\n</script>
<script>\n // get the tiddler element\n var t=window.story.findContainingTiddler(place);\n if (t && t.id!="tiddlerHideTiddlerTitle") \n for (var i=0; i<t.childNodes.length; i++)\n if (hasClass(t.childNodes[i],"title")||hasClass(t.childNodes[i],"subtitle"))\n t.childNodes[i].style.display="none";\n</script>
<script>\n var t=story.findContainingTiddler(place);\n if (t && t.id!="tiddlerHideTiddlerToolbar")\n for (var i=0; i<t.childNodes.length; i++)\n if (hasClass(t.childNodes[i],"toolbar"))\n t.childNodes[i].style.display="none";\n</script>
You can import pre-bundled tiddler "packages" directly from http://www.TiddlyTools.com/\n\nPackages combine of one or more tiddlers containing plugins, macros, wiki-formatted content, stylesheets, templates, etc. to install a set of related features and functions. Each tiddler in a package is tagged with the same tag name to make it easy to quickly identify and import all of the desired tiddlers in the set.\n\n__Please select packages to import:__\n+++{{medium{[ThemePackage (all themes)]}}}>\n__Stylesheets and background image attachments for all themes, including:__\n[[Blackout]], [[Edge of Night]], [[KubrickStylesheet]], [[Let's Get Tanked!]], [[Plain]], [[Textures]], [[TotallyTiddlers]], [[Woodshop]]\n//plus supporting CSS:// StyleSheetAdjustments and BrightText\n\nImport these tiddlers and then select a theme from the //options>themes// section in the right menu or sidebar.\n~~''source:'' http://www.TiddlyTools.com/#tag:ThemePackage~~\n +++{{big{[begin installation...]}}}...\n {{{<<loadTiddlers "tag:ThemePackage" "http://www.TiddlyTools.com/">>}}}\n <<loadTiddlers "tag:ThemePackage" "http://www.TiddlyTools.com/">>\n ===\n===\n\n+++{{medium{[MediaPackage]}}}>\n~MediaPackage combines several audio/video plugin tools to provide easy inclusion of streaming media in your document. PlayerPlugin lets you embed a Windows, Real, ~QuickTime or Flash player in a tiddler and matches known file extensions and/or specialized streaming-media transfer protocols (such as RTSP:) to automatically switch to the correct player type. DeliciousPlayTaggerPlugin adds a very compact streaming-mp3 player control preceding any .mp3 file links contained in tiddler content. MediaCenter combines ~PlayerPlugin and InlineJavascriptPlugin to provide a unified media viewing experience. You can define and select online media 'favorites' from a droplist or use media URLs from other sources (copy/paste).\n\nImport these tiddlers and then save-and-reload your document for the plugins to take effect.\n~~''source:'' http://www.TiddlyTools.com/#tag:MediaPackage~~\n +++{{big{[begin installation...]}}}...\n {{{<<loadTiddlers "tag:MediaPackage" "http://www.TiddlyTools.com/">>}}}\n <<loadTiddlers "tag:MediaPackage" "http://www.TiddlyTools.com/">>\n ===\n===\n\n+++{{medium{[TidIDEPackage]}}}>\nA full-featured tiddler editor plus key-by-key ''LIVE PREVIEW''!! Also provides diagnostic tools to help you debug your TiddlyWiki problems by letting you view current TiddlyWiki internal option values, messages, shadows, stylesheets, notify and macro functions or display the internal DOM (Document Object Model) tree structure for any specific part of the TiddlyWiki document.\n\nImport these tiddlers and then save-and-reload your document for the plugins to take effect.\n~~''source:'' http://www.TiddlyTools.com/#tag:TidIDEPackage~~\n +++{{big{[begin installation...]}}}...\n {{{<<loadTiddlers "tag:TidIDEPackage" "http://www.TiddlyTools.com/">>}}}\n <<loadTiddlers "tag:TidIDEPackage" "http://www.TiddlyTools.com/">>\n ===\n===\n\n+++{{medium{[TiddlyCardsPackage]}}}>\nTiddlyCards are like 3x5 cards with fill-in forms. TiddlyCards can display and store most of the usual HTML field control types, including: text fields, textareas (multi-line), listboxes / dropdown lists, checkboxes, and radio buttons. Each card is stored in a tiddler tagged with<<tag TiddlyCard>>, and contains two parts: an HTML form that contains the saved data values for that card, followed by an optional section of TiddlyWiki-formatted content for ''read-only'' display of card data values embedded within normal tiddler content. You can define and use multiple card types within the same document. When a card tiddler has been tagged with<<tag TiddlyCardsForm>>, it will be recognized as a ''"tear-off" form'' that can be used to create new cards. The values stored in this form definition are used as the default values when creating new cards of that type. \n\nImport these tiddlers and then save-and-reload your document for the plugins to take effect.\n~~''source:'' http://www.TiddlyTools.com/#tag:TiddlyCardsPackage~~\n +++{{big{[begin installation...]}}}...\n {{{<<loadTiddlers tag:TiddlyCardsPackage http://www.TiddlyTools.com/>>}}}\n <<loadTiddlers tag:TiddlyCardsPackage http://www.TiddlyTools.com/>>\n ===\n===
<<importTiddlers inline>>
/***\n|''Name:''|ImportTiddlersPlugin|\n|''Source:''|http://www.TiddlyTools.com/#ImportTiddlersPlugin|\n|''Author:''|Eric Shulman - ELS Design Studios|\n|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|\n|''~CoreVersion:''|2.0.10|\n\nWhen many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. It can also be very extremely helpful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\nThis plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Automatically add tags to imported tiddlers so they are easy to find later on. Generates a detailed report of import 'history' in ImportedTiddlers.\n!!!!!Interactive interface\n<<<\n{{{<<importTiddlers>>}}}\ncreates "import tiddlers" link. click to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n<<importTiddlers inline>>\n\nPress ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//\n\nSelect one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.\n\n''select: all, new, changes, or differences''\n\nYou can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:\n>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document\n>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)\n\n''Import Tagging:''\n\nTiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.\n\n''Skip, Rename, Merge, or Replace:''\n\nWhen importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.\n\nTo bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.\n\n//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//\n\n''Import Report History''\n\nWhen tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.\n\nWhen the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.\n\nIf a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.\n\nNote: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.\n\n<<<\n!!!!!non-interactive 'load tiddlers' macro\n<<<\nUseful for automated installation/update of plugins and other tiddler content.\n\n{{{<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>}}}\n<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>\n\nSyntax:\n{{{<<loadTiddlers label:text prompt:text filter source quiet confirm>>}}}\n\n''label:text'' and ''prompt:text''\n>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing. If a label is NOT provided, then no link is created and loadTiddlers() is executed whenever the containing tiddler is rendered.\n''filter'' (optional) determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler\n>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)\n>''"tiddler:~TiddlerName"'' retrieves only the specific tiddler named in the parameter.\n>''"tag:text"'' retrieves only the tiddlers tagged with the indicated text.\n''source'' (required) is the location of the imported document. It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")\n>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked\n''"quiet"'' (optional)\n>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.\n''"confirm"'' (optional)\n>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.\n<<<\n!!!!!Installation\n<<<\ncopy/paste the following tiddlers into your document:\n''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < ImportTiddlers > >" macro^^\n\n''Quick Installation Tip #1:''\nIf you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.\n<<<\n!!!!!Revision History\n<<<\n''2006.10.12 [3.0.8]'' in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)\n''2006.09.10 [3.0.7]'' in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body" \n''2006.08.16 [3.0.6]'' Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with ZW and other adaptations that hijack low-level tiddler handling. Also, in CreateImportPanel(), no longer register notify to "refresh listbox after every tiddler change" (left over from old 'auto-filtered' list handling). Thanks to Bob McElrath for report/solution.\n''2006.07.29 [3.0.5]'' added noChangeMsg to loadTiddlers processing. if not 'quiet' mode, reports skipped tiddlers.\n''2006.04.18 [3.0.4]'' in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)\n''2006.04.12 [3.0.3]'' moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.\n''2006.04.12 [3.0.2]'' additional refactoring of 'core candidate' code. Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.\n''2006.04.04 [3.0.1]'' in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section\n''2006.04.04 [3.0.0]'' Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.\n''2006.03.30 [2.9.1]'' when extracting store area from remote URL, look for "</body>" instead of "</body>\sn</html>" so it will match even if the "\sn" is absent from the source.\n''2006.03.30 [2.9.0]'' added optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.\n''2006.03.28 [2.8.1]'' in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (IE does *not* define these values, so we bypass this code)\nAlso, when extracting store area from remote URL, explicitly look for "</body>\sn</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities. Thanks to Tom Otvos for finding these bugs and suggesting some fixes.\n''2006.02.21 [2.8.0]'' added support for "tiddler:TiddlerName" filtering parameter in auto-import processing\n''2006.02.21 [2.7.1]'' Clean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)\n''2006.02.21 [2.7.0]'' Added "local file" and "web server" radio buttons for selecting dynamic import source controls in ImportPanel. Default file control is replaced with URL text input field when "web server" is selected. Default remote document URL is defined in SiteURL tiddler. Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)\n''2006.02.17 [2.6.0]'' Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]'' added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]'' FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]'' corrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]'' moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]'' added checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]'' added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]'' Added support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]'' Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]'' Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]'' Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]'' Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]'' When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]'' IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]'' When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]'' When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]'' Update for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.22 [1.3.1]'' tweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]'' Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]'' fixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]'' added 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]'' only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]'' fixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]'' combined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]'' moved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]'' core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]'' added parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]'' Initial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // ''MACRO DEFINITION''\n//{{{\n// Version\nversion.extensions.importTiddlers = {major: 3, minor: 0, revision: 8, date: new Date(2006,10,12)};\n\n// IE needs explicit global scoping for functions/vars called from browser events\nwindow.onClickImportButton=onClickImportButton;\nwindow.refreshImportList=refreshImportList;\n\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.importTiddlers = { };\nconfig.macros.importTiddlers = {\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n foundMsg: "Found %0 tiddlers in %1",\n countMsg: "%0 tiddlers selected for import",\n importedMsg: "Imported %0 of %1 tiddlers from %2",\n src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)\n proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)\n useProxy: false, // use specific proxy script in front of remote URL\n inbound: null, // hash-indexed array of tiddlers from other document\n newTags: "", // text of tags added to imported tiddlers\n addTags: true, // add new tags to imported tiddlers\n listsize: 8, // # of lines to show in imported tiddler list\n importTags: true, // include tags from remote source document when importing a tiddler\n keepTags: true, // retain existing tags when replacing a tiddler\n index: 0, // current processing index in import list\n sort: "" // sort order for imported tiddler listbox\n};\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params) {\n if (!config.macros.loadTiddlers.handler)\n { alert("importTiddlers error: this plugin requires LoadTiddlersPlugin or TiddlyWiki 2.1+"); return; }\n if (!params[0]) // LINK TO FLOATING PANEL\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n else if (params[0]=="inline") {// // INLINE TIDDLER CONTENT\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n }\n else config.macros.loadTiddlers.handler(place,macroName,params); // FALLBACK: PASS TO LOADTIDDLERS\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\n\n// // Handle link click to create/show/hide control panel\n//{{{\nfunction onClickImportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("importPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createImportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n// // Create control panel: HTML, CSS\n//{{{\nfunction createImportPanel(place) {\n var panel=document.getElementById("importPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.importTiddlers.css,"importTiddlers");\n panel=createTiddlyElement(place,"span","importPanel",null,null)\n panel.innerHTML=config.macros.importTiddlers.html;\n refreshImportList();\n var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";\n document.getElementById("importSourceURL").value=siteURL;\n config.macros.importTiddlers.src=siteURL;\n var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";\n document.getElementById("importSiteProxy").value=siteProxy;\n config.macros.importTiddlers.proxy=siteProxy;\n return panel;\n}\n//}}}\n\n// // CSS\n//{{{\nconfig.macros.importTiddlers.css = '\s\n#importPanel {\s\n display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\s\n background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#importPanel .rad { width:auto; }\s\n#importPanel .chk { width:auto; margin:1px;border:0; }\s\n#importPanel .btn { width:auto; }\s\n#importPanel .btn1 { width:98%; }\s\n#importPanel .btn2 { width:48%; }\s\n#importPanel .btn3 { width:32%; }\s\n#importPanel .btn4 { width:24%; }\s\n#importPanel .btn5 { width:19%; }\s\n#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\s\n#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\s\n#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML \n//{{{\nconfig.macros.importTiddlers.html = '\s\n<!-- source and report -->\s\n<table><tr><td align=left>\s\n import from\s\n <input type="radio" class="rad" name="importFrom" value="file" CHECKED\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=!this.checked?\s'block\s':\s'none\s'"> local file\s\n <input type="radio" class="rad" name="importFrom" value="http"\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=!this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=this.checked?\s'block\s':\s'none\s'"> web server\s\n</td><td align=right>\s\n <input type=checkbox class="chk" id="chkImportReport" checked\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;"> create a report\s\n</td></tr></table>\s\n<!-- import from local file -->\s\n<div id="importLocalPanel" style="display:block;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\nlocal document path/filename:<br>\s\n<input type="file" id="fileImportSource" size=57 style="width:100%"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<!-- import from http server -->\s\n<div id="importHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\n<table><tr><td align=left>\s\n remote document URL:<br>\s\n</td><td align=right>\s\n <input type="checkbox" class="chk" id="importUseProxy"\s\n onClick="config.macros.importTiddlers.useProxy=this.checked;\s\n document.getElementById(\s'importSiteProxy\s').style.display=this.checked?\s'block\s':\s'none\s'"> use a proxy script\s\n</td></tr></table>\s\n<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\s\n onKeyUp="config.macros.importTiddlers.proxy=this.value"\s\n onChange="config.macros.importTiddlers.proxy=this.value;">\s\n<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<table><tr><td align=left>\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n added </a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n changes </a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n differences </a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align=right>\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n + </a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n = </a>\s\n</td></tr></table>\s\n<select id="importList" size=8 multiple\s\n onchange="setTimeout(\s'refreshImportList(\s'+this.selectedIndex+\s')\s',1)">\s\n <!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\s\n</select>\s\n<input type=checkbox class="chk" id="chkAddTags" checked\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \s\n<input type=checkbox class="chk" id="chkImportTags" checked\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \s\n<input type=checkbox class="chk" id="chkKeepTags" checked\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\s\n<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\s\n<div align=center>\s\n <input type=button id="importOpen" class="importButton" style="width:32%" value="open"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importStart" class="importButton" style="width:32%" value="import"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importClose" class="importButton" style="width:32%" value="close"\s\n onclick="onClickImportButton(this)">\s\n</div>\s\n<div id="importCollisionPanel">\s\n tiddler already exists:\s\n <input type=text id="importNewTitle" size=15 autocomplete=off">\s\n <div align=center>\s\n <input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importRename" class="importButton" style="width:23%" value="rename"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\s\n onclick="onClickImportButton(this)">\s\n </div>\s\n</div>\s\n';\n//}}}\n\n// // Control interactions\n//{{{\nfunction onClickImportButton(which)\n{\n // DEBUG alert(which.id);\n var theList = document.getElementById('importList');\n if (!theList) return;\n var thePanel = document.getElementById('importPanel');\n var theCollisionPanel = document.getElementById('importCollisionPanel');\n var theNewTitle = document.getElementById('importNewTitle');\n var count=0;\n switch (which.id)\n {\n case 'fileImportSource':\n case 'importOpen': // load import source into hidden frame\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n if (config.macros.importTiddlers.src=="") break;\n // Load document into hidden iframe so we can read it's DOM and fill the list\n loadRemoteFile(config.macros.importTiddlers.src, function(src,txt) {\n var tiddlers = readTiddlersFromHTML(txt);\n var count=tiddlers?tiddlers.length:0;\n displayMessage(config.macros.importTiddlers.foundMsg.format([count,src]));\n config.macros.importTiddlers.inbound=tiddlers;\n window.refreshImportList(0);\n });\n break;\n case 'importSelectAll': // select all tiddler list items (i.e., not headings)\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count++;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectNew': // select tiddlers not in current document\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importToggleFilter': // show/hide filter\n case 'importFilter': // apply filter\n alert("coming soon!");\n break;\n case 'importStart': // initiate the import processing\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.index=0;\n config.macros.importTiddlers.index=importTiddlers(0);\n importStopped();\n break;\n case 'importClose': // unload imported tiddlers or hide the import control panel\n // if imported tiddlers not loaded, close the import control panel\n if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n break;\n case 'importSkip': // don't import the tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status='skipped after asking'; // mark item as skipped\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item\n importStopped();\n break;\n case 'importRename': // change name of imported tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status = 'renamed from '+theImported.title; // mark item as renamed\n theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title\n theItem.value = theNewTitle.value; // change the listbox item text\n theItem.text = theNewTitle.value; // change the listbox item text\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importMerge': // join existing and imported tiddler content\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n var theText = theExisting.text+'\sn----\sn^^merged from: ';\n theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn';\n theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\sn'+theImported.text;\n var theDate = new Date();\n var theTags = theExisting.getTags()+' '+theImported.getTags();\n theImported.set(null,theText,null,theDate,theTags);\n theImported.status = 'merged with '+theExisting.title; // mark item as merged\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item\n importStopped();\n break;\n case 'importReplace': // substitute imported tiddler for existing tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n theImported.status = 'replaces '+theExisting.title; // mark item for replace\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importListSmaller': // decrease current listbox size, minimum=5\n if (theList.options.length==1) break;\n theList.size-=(theList.size>5)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListLarger': // increase current listbox size, maximum=number of items in list\n if (theList.options.length==1) break;\n theList.size+=(theList.size<theList.options.length)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListMaximize': // toggle listbox size between current and maximum\n if (theList.options.length==1) break;\n theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;\n break;\n }\n}\n//}}}\n\n// // refresh listbox\n//{{{\nfunction refreshImportList(selectedIndex)\n{\n var theList = document.getElementById("importList");\n if (!theList) return;\n // if nothing to show, reset list content and size\n if (!config.macros.importTiddlers.inbound) \n {\n while (theList.length > 0) { theList.options[0] = null; }\n theList.options[0]=new Option('please open a document...',"",false,false);\n theList.size=config.macros.importTiddlers.listsize;\n return;\n }\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading\n if (selectedIndex==1) config.macros.importTiddlers.sort='title';\n if (selectedIndex==2) config.macros.importTiddlers.sort='modified';\n if (selectedIndex==3) config.macros.importTiddlers.sort='tags';\n if (selectedIndex>3) {\n // display selected tiddler count\n for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n return; // no refresh needed\n }\n\n // get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)\n var tiddlers=config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);\n // output the tiddler list\n switch(config.macros.importTiddlers.sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++) {\n var tiddler = tiddlers[t];\n var theSection = tiddler.modified.toLocaleDateString();\n if (theSection != lastSection) {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n case "tags":\n var theTitles = {}; // all tiddler titles, hash indexed by tag value\n var theTags = new Array();\n for(var t=0; t<tiddlers.length; t++) {\n var title=tiddlers[t].title;\n var tags=tiddlers[t].tags;\n if (!tags || !tags.length) {\n if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }\n theTitles["untagged"].push(title);\n }\n else for(var s=0; s<tags.length; s++) {\n if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }\n theTitles[tags[s]].push(title);\n }\n }\n theTags.sort();\n for(var tagindex=0; tagindex<theTags.length; tagindex++) {\n var theTag=theTags[tagindex];\n theList.options[i++]=new Option(theTag,"",false,false);\n for(var t=0; t<theTitles[theTag].length; t++)\n theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;\n if (theList.size>theList.options.length) theList.size=theList.options.length;\n}\n//}}}\n\n// // re-entrant processing for handling import with interactive collision prompting\n//{{{\nfunction importTiddlers(startIndex)\n{\n if (!config.macros.importTiddlers.inbound) return -1;\n\n var theList = document.getElementById('importList');\n if (!theList) return;\n var t;\n // if starting new import, reset import status flags\n if (startIndex==0)\n for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)\n config.macros.importTiddlers.inbound[t].status="";\n for (var i=startIndex; i<theList.options.length; i++)\n {\n // if list item is not selected or is a heading (i.e., has no value), skip it\n if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))\n continue;\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==t) break;\n var inbound = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(inbound.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (inbound.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (inbound.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))\n return i;\n // assemble tags (remote + existing + added)\n var newTags = "";\n if (config.macros.importTiddlers.importTags)\n newTags+=inbound.getTags() // import remote tags\n if (config.macros.importTiddlers.keepTags && theExisting)\n newTags+=" "+theExisting.getTags(); // keep existing tags\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newTags+=" "+config.macros.importTiddlers.newTags; // add new tags\n inbound.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n inbound.status=(inbound.status=="")?'added':inbound.status;\n // do the import!\n // OLD: store.addTiddler(in); store.setDirty(true);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\n }\n return(-1); // signals that we really finished the entire list\n}\n//}}}\n\n//{{{\nfunction importStopped()\n{\n var theList = document.getElementById('importList');\n var theNewTitle = document.getElementById('importNewTitle');\n if (!theList) return;\n if (config.macros.importTiddlers.index==-1)\n importReport(); // import finished... generate the report\n else\n {\n // DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);\n // import collision... show the collision panel and set the title edit field\n document.getElementById('importCollisionPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n//{{{\nfunction importReport(quiet)\n{\n if (!config.macros.importTiddlers.inbound) return;\n // DEBUG alert('importReport: start');\n\n // if import was not completed, the collision panel will still be open... close it now.\n var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';\n\n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n // gather the statistics\n var count=0;\n for (var t=0; t<tiddlers.length; t++)\n if (tiddlers[t].status && tiddlers[t].status.trim().length && tiddlers[t].status.substr(0,7)!="skipped") count++;\n\n // generate a report\n if (count && config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName\n newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\sn[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\sn";\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newText += "imported tiddlers were tagged with: \s""+config.macros.importTiddlers.newTags+"\s"\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n\n // reset status flags\n for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";\n\n // refresh display if tiddlers have been loaded\n if (count) { store.setDirty(true); store.notifyAll(); }\n\n // always show final message when tiddlers were actually loaded\n if (count) displayMessage(config.macros.importTiddlers.importedMsg.format([count,tiddlers.length,config.macros.importTiddlers.src]));\n}\n//}}}\n\n/***\n!!!!!TW 2.1beta Core Code Candidate\n//The following section is a preliminary 'code candidate' for incorporation of non-interactive 'load tiddlers' functionality into TW2.1beta. //\n***/\n//{{{\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.loadTiddlers = {\n label: "",\n prompt: "add/update tiddlers from '%0'",\n askMsg: "Please enter a local path/filename or a remote URL",\n openMsg: "Opening %0",\n openErrMsg: "Could not open %0 - error=%1",\n readMsg: "Read %0 bytes from %1",\n foundMsg: "Found %0 tiddlers in %1",\n nochangeMsg: "'%0' is up-to-date... skipped.",\n loadedMsg: "Loaded %0 of %1 tiddlers from %2"\n};\n\nconfig.macros.loadTiddlers.handler = function(place,macroName,params) {\n var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;\n var prompt=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.prompt;\n var filter="updates";\n if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'\n || params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))\n filter=params.shift();\n var src=params.shift(); if (!src || !src.length) return; // filename is required\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="confirm"); if (ask) params.shift();\n var force=(params[0]=="force"); if (force) params.shift();\n if (label.trim().length) {\n // link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store\n createTiddlyButton(place,label.format([src]),prompt.format([src]), function() {\n if (src=="ask") src=prompt(config.macros.loadTiddlers.askMsg);\n loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n })\n }\n else {\n // load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store\n if (src=="ask") src=prompt(config.macros.loadTiddlers.askMsg);\n loadRemoteFile(src,loadTiddlers,quiet,ask,filter,force);\n }\n}\n\nfunction loadTiddlers(src,html,quiet,ask,filter,force)\n{\n var tiddlers = readTiddlersFromHTML(html);\n var count=tiddlers?tiddlers.length:0;\n if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src]));\n var count=0;\n if (tiddlers) for (var t=0;t<tiddlers.length;t++) {\n var inbound = tiddlers[t];\n var theExisting = store.getTiddler(inbound.title);\n if (inbound.title=='ImportedTiddlers')\n continue; // skip "ImportedTiddlers" history from the other document...\n\n // apply the all/new/changes/updates filter (if any)\n if (filter && filter!="all") {\n if ((filter=="new") && theExisting) // skip existing tiddlers\n continue;\n if ((filter=="changes") && !theExisting) // skip new tiddlers\n continue;\n if ((filter.substr(0,4)=="tag:") && inbound.tags.find(filter.substr(4))==null) // must match specific tag value\n continue;\n if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name\n continue;\n if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))\n { if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }\n }\n // get confirmation if required\n if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\snfrom "+src))\n { tiddlers[t].status="skipped - cancelled by user"; continue; }\n // DO IT!\n // OLD: store.addTiddler(in);\n store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);\n store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value\n tiddlers[t].status=theExisting?"updated":"added"\n count++;\n }\n if (count) {\n // refresh display\n store.setDirty(true);\n store.notifyAll();\n // generate a report\n if (config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName+" loaded "+count+" tiddlers from\sn[["+src+"|"+src+"]]:\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n// 20060918 ELS: DON'T ADD "discard" BUTTON TO REPORT\n// newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n// newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n// newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n // OLD: store.addTiddler(theReport);\n store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n }\n // always show final message when tiddlers were actually loaded\n if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src]));\n}\n\nfunction loadRemoteFile(src,callback,quiet,ask,filter,force) {\n if (src==undefined || !src.length) return null; // filename is required\n if (!quiet) clearMessage();\n if (!quiet) displayMessage(config.macros.loadTiddlers.openMsg.format([src]));\n if (src.substr(0,4)!="http" && src.substr(0,4)!="file") { // if not a URL, fallback to read from local filesystem\n var txt=loadFile(src);\n if ((txt==null)||(txt==false)) // file didn't load\n { if (!quiet) displayMessage(config.macro