|''Type:''|file|
|''URL:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Workspace:''|(default)|
This tiddler was automatically created to record the details of this server
/***
|Name|BetterTimelineMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#BetterTimelineMacro|
|Version|0.5 beta|
|Requires|~TW2.x|
!!!Description:
A replacement for the core timeline macro that offers more features:
*list tiddlers with only specfic tag
*exclude tiddlers with a particular tag
*limit entries to any number of days, for example one week
*specify a start date for the timeline, only tiddlers after that date will be listed.
!!!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.
Edit the ViewTemplate to add the fullscreen command to the toolbar.
!!!Syntax:
{{{<<timeline better:true>>}}}
''the param better:true enables the advanced features, without it you will get the old timeline behaviour.''
additonal params:
(use only the ones you want)
{{{<<timeline better:true onlyTag:Tag1 excludeTag:Tag2 sortBy:modified/created firstDay:YYYYMMDD maxDays:7 maxEntries:30>>}}}
''explanation of syntax:''
onlyTag: only tiddlers with this tag will be listed. Default is to list all tiddlers.
excludeTag: tiddlers with this tag will not be listed.
sortBy: sort tiddlers by date modified or date created. Possible values are modified or created.
firstDay: useful for starting timeline from a specific date. Example: 20060701 for 1st of July, 2006
maxDays: limits timeline to include only tiddlers from the specified number of days. If you use a value of 7 for example, only tiddlers from the last 7 days will be listed.
maxEntries: limit the total number of entries in the timeline.
!!!History:
*28-07-06: ver 0.5 beta, first release
!!!Code
***/
//{{{
// Return the tiddlers as a sorted array
TiddlyWiki.prototype.getTiddlers = function(field,excludeTag,includeTag)
{
var results = [];
this.forEachTiddler(function(title,tiddler)
{
if(excludeTag == undefined || tiddler.tags.find(excludeTag) == null)
if(includeTag == undefined || tiddler.tags.find(includeTag)!=null)
results.push(tiddler);
});
if(field)
results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
return results;
}
//this function by Udo
function getParam(params, name, defaultValue)
{
if (!params)
return defaultValue;
var p = params[0][name];
return p ? p[0] : defaultValue;
}
window.old_timeline_handler= config.macros.timeline.handler;
config.macros.timeline.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var args = paramString.parseParams("list",null,true);
var betterMode = getParam(args, "better", "false");
if (betterMode == 'true')
{
var sortBy = getParam(args,"sortBy","modified");
var excludeTag = getParam(args,"excludeTag",undefined);
var includeTag = getParam(args,"onlyTag",undefined);
var tiddlers = store.getTiddlers(sortBy,excludeTag,includeTag);
var firstDayParam = getParam(args,"firstDay",undefined);
var firstDay = (firstDayParam!=undefined)? firstDayParam: "00010101";
var lastDay = "";
var field= sortBy;
var maxDaysParam = getParam(args,"maxDays",undefined);
var maxDays = (maxDaysParam!=undefined)? maxDaysParam*24*60*60*1000: (new Date()).getTime() ;
var maxEntries = getParam(args,"maxEntries",undefined);
var last = (maxEntries!=undefined) ? tiddlers.length-Math.min(tiddlers.length,parseInt(maxEntries)) : 0;
for(var t=tiddlers.length-1; t>=last; t--)
{
var tiddler = tiddlers[t];
var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
if ((theDay>=firstDay)&& (tiddler[field].getTime()> (new Date()).getTime() - maxDays))
{
if(theDay != lastDay)
{
var theDateList = document.createElement("ul");
place.appendChild(theDateList);
createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(this.dateFormat));
lastDay = theDay;
}
var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink",null);
theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
}
}
}
else
{
window.old_timeline_handler.apply(this,arguments);
}
}
//}}}
/***
|Name|BlogViewPlugin|
|Created by|Craig Rindt|
|Location|http://parsons.its.uci.edu/~crindt/noteblog.html#BlogViewPlugin|
|Version|0.21|
|Requires|~TW2.x|
!!!Description:
Open a user defined number of recent tiddlers automatically when the TW loads.
You can also specify a tag and only load tiddlers that have that tag.
To change the number of tiddlers automatically opened, or define a tag to use, ed the config.autoOpenTiddlers part of the code below.
A fork of [[AutoOpenTiddlersPlugin|http://tw.lewcid.org/#AutoOpenTiddlersPlugin]]
!!!Code
***/
//{{{
//edit this section to change the default settings
config.blogViewTiddlers =
{
count: 5, //number of tiddlers opened.
tag: 'Blog' //change if you want to open tiddlers with a specific tag, eg: 'DefaultTiddlers'
}
config.blogViewTiddlers.handler = function()
{
if (this.tag == undefined)
var newTiddlers = store.getTiddlers( 'modified' );
else
var newTiddlers = store.getTaggedTiddlers(this.tag, 'modified' );
var newTiddlers = newTiddlers.reverse();
var max = Math.min(this.count,newTiddlers.length-1);
for (var i=max; i>=0; i--)
{ story.displayTiddler(null,newTiddlers[i].title);}
var staticTiddlers = store.getTaggedTiddlers( 'Static content', 'modified' );
var staticTiddlers = staticTiddlers.reverse();
for ( var i = staticTiddlers.length-1; i >= 0; i-- )
{ story.displayTiddler( null, staticTiddlers[ i ].title ); }
}
window.old_blogViewTiddlers_restart = restart;
restart = function ()
{
window.old_blogViewTiddlers_restart();
config.blogViewTiddlers.handler();
}
//}}}
/***
|Name|BreadcrumbsPlugin|
|Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|
|OriginalAuthor|Alan Hecht (with 2.0 update from 'jack' and revisions by Bram Chen)|
|Version|1.5.7.0TT|
|Author|Eric Shulman|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler,TiddlyWiki.prototype.deleteTiddler|
|Description|show a list of tiddlers viewed during this session. Also defines "back" (previousTiddler) toolbar button and macro|
!Configuration
<<<
<<option chkShowBreadcrumbs>> show breadcrumbs display
>//Note: although this checkbox does toggle the breadcrumbs ''setting'', the actual breadcrumbs ''display'' is not updated until the next crumb is added (or a previous crumb is clicked on). In order for the checkbox setting to have ''immediate'' effect, please see [[ToggleBreadcrumbs]], which uses [[InlineJavascriptPlugin]] to synchronize the checkbox setting and the breadcrumbs display.//
<<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler
>//Note: standard (non-enabled) behavior is to ''trim'' the breadcrumbs list when visiting a previously viewed tiddler, so that all crumbs following that tiddler are removed from the list.//
<<<
!Revision History:
__TiddlyTools (TT) variant:__
1.5.8.0 2007.05.26 - added support for {{{<<option chkReorderBreadcrumbs>>}}} to toggle trim vs. re-order behavior when visiting previously viewed tiddlers
1.5.7.0 2007.05.25 - added support for {{{<<option chkShowBreadcrumbs>>}}} to toggle //display// of breadcrumbs
1.5.6.0 2007.05.24 - in refreshCrumbs(), remove non-existing tiddler titles from crumb list. Also, hijack deleteTiddler() so crumbs can be updated after tiddler is deleted.
1.5.5.0 2007.04.11 - added optional params to previousTiddler macro handler() to allow alternative label and tooltip text (instead of default "back")
1.5.4.0 2007.03.02 - in refreshCrumbs(), for TW2.2, look for "storyDisplay" instead of "tiddlerDisplay" but keep fallback to "tiddlerDisplay" for TW2.1 or earlier
1.5.3.0 2007.02.24 - changed from hijack of onClickTiddlerLink to hijack of displayTiddler() so that ALL displayed tiddlers are recorded in the crumbs, including programmatically displayed tiddlers opened by macros, scripts, etc., (such as [[GotoPlugin]], among many others) in addition to those opened by clicks on links.
1.5.2.0 2007.02.24 - eliminated global space clutter by moving function and data declarations so they are contained inside config.breadCrumbs object.
1.5.1.0 2007.02.06 - added "previousTiddler" macro (for use in sidebar)
1.5.0.0 2007.02.05 - added "previousTiddler" toolbar command (aka, "back")
1.4.0.1 2006.08.04 - change spaces to tabs
1.4.0.0 2006.08.04 - modified from 1.4.0 distro:
<<<
in refreshCrumbs(), set {{{display:none/block}}} instead of {{{visibility:hidden/visible}}}
in restartHome(), check for valid crumbArea before setting style
general code cleanup/reformat using tabs to indent
<<<
|1.4.0|Aug 02, 2006|Fixed bug, the redefined onClickTiddlerLink_orig_breadCrumbs works incorrectly on IE|
|1.3.0|Jul 20, 2006|Runs compatibly with TW 2.1.0 (rev #403+)|
|1.2.0|Feb 07, 2006|change global array breadCrumbs to config.breadCrumbs by Eric's suggestion|
|1.1.0|Feb 04, 2006|JSLint checked|
|1.0.0|Feb 01, 2006|TW2 ready and code Cleaned-up|
!Code section:
***/
//{{{
version.extensions.breadCrumbs = {major: 1, minor: 5, revision: 8, date: new Date("May 26, 2007")};
// show/hide display option (default is to SHOW breadcrumbs)
if (config.options.chkShowBreadcrumbs==undefined)
config.options.chkShowBreadcrumbs=true;
// REORDER breadcrumbs when visiting previously viewed tiddler (default is to TRIM breadcrumbs)
if (config.options.chkReorderBreadcrumbs==undefined)
config.options.chkReorderBreadcrumbs=false;
// hijack story.displayTiddler() so crumbs can be refreshed when a tiddler is displayed
if (Story.prototype.breadCrumbs_coreDisplayTiddler==undefined)
Story.prototype.breadCrumbs_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
this.breadCrumbs_coreDisplayTiddler.apply(this,arguments);
// if not displaying tiddler during document startup, then add it to the breadcrumbs
// note: 'startingUp' flag is a global, set/reset by the core init() function
if (!startingUp) config.breadCrumbs.addCrumb(title);
}
// hijack store.removeTiddler() so crumbs can be refreshed when a tiddler is deleted
if (TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler==undefined)
TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler=TiddlyWiki.prototype.removeTiddler;
TiddlyWiki.prototype.removeTiddler= function(title)
{
this.breadCrumbs_coreRemoveTiddler.apply(this,arguments);
config.breadCrumbs.refreshCrumbs();
}
config.breadCrumbs = {
crumbs: [], // the list of current breadcrumbs
addCrumb: function (title) { // ELS: changed from passing event, "e", to passing tiddler title
var thisCrumb = "[[" + title + "]]";
var ind = this.crumbs.find(thisCrumb);
if(ind === null)
this.crumbs.push(thisCrumb);
else if (config.options.chkReorderBreadcrumbs)
this.crumbs.push(this.crumbs.splice(ind,1)[0]); // reorder crumbs
else
this.crumbs=this.crumbs.slice(0,ind+1); // trim crumbs
this.refreshCrumbs();
return false;
},
refreshCrumbs: function() {
var crumbArea = document.getElementById("breadCrumbs");
if (!crumbArea) {
var crumbArea = document.createElement("div");
crumbArea.id = "breadCrumbs";
crumbArea.style.display= "none";
var targetArea= document.getElementById("tiddlerDisplay"); // TW2.1-
if (!targetArea) targetArea = document.getElementById("storyDisplay"); // TW2.2+
targetArea.parentNode.insertBefore(crumbArea,targetArea);
}
crumbArea.style.display = config.options.chkShowBreadcrumbs?"block":"none";
removeChildren(crumbArea);
createTiddlyButton(crumbArea,"Home",null,this.restartHome);
for (c=0; c<this.crumbs.length; c++)
if (!store.tiddlerExists(this.crumbs[c].replace(/\[\[/,'').replace(/\]\]/,'')))
this.crumbs.splice(c,1); // remove non-existing tiddler from crumbs
wikify(" | " + this.crumbs.join(' > '),crumbArea);
},
restartHome: function() {
story.closeAllTiddlers();
restart();
config.breadCrumbs.crumbs = [];
var crumbArea = document.getElementById("breadCrumbs");
if (crumbArea) crumbArea.style.display = "none";
}
};
config.commands.previousTiddler = {
text: 'back',
tooltip: 'view the previous tiddler',
hideReadOnly: false,
dateFormat: 'DDD, MMM DDth YYYY hh:0mm:0ss',
handler: function(event,src,title) {
var here=story.findContainingTiddler(src); if (!here) return;
if (config.breadCrumbs.crumbs.length>1) {
var crumb=config.breadCrumbs.crumbs[config.breadCrumbs.crumbs.length-2].replace(/\[\[/,'').replace(/\]\]/,'');
story.displayTiddler(here,crumb);
}
else
config.breadCrumbs.restartHome();
return false;
}
};
config.macros.previousTiddler= {
label: 'back',
prompt: 'view the previous tiddler',
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var label=params.shift(); if (!label) label=this.label;
var prompt=params.shift(); if (!prompt) prompt=this.prompt;
createTiddlyButton(place,label,prompt,function() {
if (config.breadCrumbs.crumbs.length>1) {
var crumb=config.breadCrumbs.crumbs[config.breadCrumbs.crumbs.length-2].replace(/\[\[/,'').replace(/\]\]/,'');
story.displayTiddler(place,crumb);
}
else
config.breadCrumbs.restartHome();
});
}
}
//}}}
A project funded by Caltrans to have the [[Institute of Transportation Studies, Irvine]] develop on-line courseware for their technical staff and managers.
Cartesius is a multi-agent, multi-jurisdictional incident management system created by [[Fillipo Logi]] for his Ph.D. dissertation at the [[UC Irvine]].
[[My|Craig Rindt]] involvement with began as a support role during its original development and has evolved to the point that I am the maintainer and primary (OK, sole) developer of the system. The most recent work on Cartesius is being performed as part of the [[Cartesius/CTNET]] project.
The Cartesius/CTNET project is an effort to integrate the [[Cartesius]] multi-jurisdictional traffic management system with the [[CTNET]] traffic signal management system created by [[Caltrans]].
Craig Rindt is me. I am a postdoctoral researcher at the [[Institute of Transportation Studies|http://www.its.uci.edu]] at [[UC Irvine|http://www.uci.edu]] where I obtained my Ph.D. in Transportation Engineering in 2003.
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Version|2.3.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a local file|
When 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.)
ExportTiddlersPlugin 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.''
!!!!!Inline interface (live)
<<<
<<exportTiddlers inline>>
<<<
!!!!!Usage
<<<
Optional "special tiddlers" used by this plugin:
* SiteUrl^^
URL for official server-published version of document being viewed (used in XML export)
default: //none//^^
* SiteHost^^
host name/address for remote server (e.g., "www.server.com" or "192.168.1.27")
default: //none//^^
* SitePost^^
remote path/filename for submitting changes (e.g., "/cgi-bin/submit.cgi")
default: //none//^^
* SiteParams^^
arguments (if any) for server-side receiving script
default: //none//^^
* SiteNotify^^
addresses (if any) for sending automatic server-side email notices
default: //none//^^
* SiteID^^
username or other authorization identifier for login-controlled access to remote server
default: current TiddlyWiki username (e.g., "YourName")^^
* SiteDate^^
stored date/time stamp for most recent published version of document
default: current document.modified value (i.e., the 'file date')^^
<<<
!!!!!Example
<<<
<<exportTiddlers>>
<<<
!!!!!Installation
<<<
Import (or copy/paste) the following tiddlers into your document:
''ExportTiddlersPlugin'' (tagged with <<tag systemConfig>>)
create/edit ''SideBarOptions'': (sidebar menu items)
^^Add {{{<<exportTiddlers>>}}} macro^^
<<<
!!!!!Revision History
<<<
''2007.04.19 [2.3.0]'' in exportData(), pass SiteURL value as param to saveToRss(). Fixes 'undefined' appearing in tiddler link in XML output. Also, in refreshExportList(), added 'sort by tags'. Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
''2007.03.02 [2.2.6]'' in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" instead of "tiddlerDisplay" but keep fallback to "tiddlerDisplay" for TW2.1 or earlier
''2007.03.01 [2.2.5]'' removed hijack of store.saveChanges() (was catching save on http:, but there are other solutions that do a much better job of handling save to server.
|please see [[ExportTiddlersPluginHistory]] for additional revision details|
''2005.10.09 [0.0.0]'' development started
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.exportTiddlers = {major: 2, minor: 3, revision: 0, date: new Date(2007,4,19)};
//}}}
// // macro handler
//{{{
config.macros.exportTiddlers = {
label: "export tiddlers",
prompt: "Copy selected tiddlers to an export document",
newdefault: "export.html",
datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields
};
config.macros.exportTiddlers.handler = function(place,macroName,params) {
if (params[0]!="inline")
{ createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }
var panel=createExportPanel(place);
panel.style.position="static";
panel.style.display="block";
}
function createExportPanel(place) {
var panel=document.getElementById("exportPanel");
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");
panel=createTiddlyElement(place,"span","exportPanel",null,null)
panel.innerHTML=config.macros.exportTiddlers.html;
exportShowPanel(document.location.protocol);
exportInitFilter();
refreshExportList(0);
return panel;
}
function onClickExportMenu(e)
{
if (!e) var e = window.event;
var parent=resolveTarget(e).parentNode;
var panel = document.getElementById("exportPanel");
if (panel==undefined || panel.parentNode!=parent)
panel=createExportPanel(parent);
var isOpen = panel.style.display=="block";
if(config.options.chkAnimate)
anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
else
panel.style.display = isOpen ? "none" : "block" ;
if (panel.style.display!="none") refreshExportList(0); // update list when panel is made visible
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
// // IE needs explicit scoping for functions called by browser events
//{{{
window.onClickExportMenu=onClickExportMenu;
window.onClickExportButton=onClickExportButton;
window.exportShowPanel=exportShowPanel;
window.exportShowFilterFields=exportShowFilterFields;
window.refreshExportList=refreshExportList;
//}}}
// // CSS for floating export control panel
//{{{
config.macros.exportTiddlers.css = '\
#exportPanel {\
display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\
background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
#exportPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }\
#exportPanel textarea { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\
#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px; }\
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#exportPanel .rad { width:auto;border:0 }\
#exportPanel .chk { width:auto;border:0 }\
#exportPanel .btn { width:auto; }\
#exportPanel .btn1 { width:98%; }\
#exportPanel .btn2 { width:48%; }\
#exportPanel .btn3 { width:32%; }\
#exportPanel .btn4 { width:24%; }\
#exportPanel .btn5 { width:19%; }\
';
//}}}
// // HTML for export control panel interface
//{{{
config.macros.exportTiddlers.html = '\
<!-- output target and format -->\
<table cellpadding="0" cellspacing="0"><tr><td width=50%>\
export to\
<select size=1 id="exportTo" onchange="exportShowPanel(this.value);">\
<option value="file:" SELECTED>this computer</option>\
<option value="http:">web server (http)</option>\
<option value="https:">secure web server (https)</option>\
<option value="ftp:">file server (ftp)</option>\
</select>\
</td><td width=50%>\
output format\
<select id="exportFormat" size=1>\
<option value="DIV">TiddlyWiki export file</option>\
<option value="TW">TiddlyWiki document</option>\
<option value="XML">RSS feed (XML)</option>\
</select>\
</td></tr></table>\
\
<!-- export to local file -->\
<div id="exportLocalPanel" style="margin-top:5px;">\
local path/filename<br>\
<input type="text" id="exportFilename" size=40 style="width:93%"><input \
type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
onclick="this.previousSibling.value=window.promptForExportFilename(this);">\
<!--<input type="file" id="exportFilename" size=57 style="width:100%"><br>-->\
</div><!--panel-->\
\
<!-- export to http server -->\
<div id="exportHTTPPanel" style="display:none;margin-top:5px;">\
<table><tr><td align=left>\
server location, script, and parameters<br>\
</td><td align=right>\
<input type="checkbox" class="chk" id="exportNotify"\
onClick="document.getElementById(\'exportSetNotifyPanel\').style.display=this.checked?\'block\':\'none\'"> notify\
</td></tr></table>\
<input type="text" id="exportHTTPServerURL" onfocus="this.select()"><br>\
<div id="exportSetNotifyPanel" style="display:none">\
send email notices to<br>\
<input type="text" id="exportNotifyTo" onfocus="this.select()"><br>\
</div>\
</div><!--panel-->\
\
<!-- export to ftp server -->\
<div id="exportFTPPanel" style="display:none;margin-top:5px;">\
<table cellpadding="0" cellspacing="0" width="32%"><tr valign="top"><td>\
host server<br>\
<input type="text" id="exportFTPHost" onfocus="this.select()"><br>\
</td><td width="32%">\
username<br>\
<input type="text" id="exportFTPID" onfocus="this.select()"><br>\
</td><td width="32%">\
password<br>\
<input type="password" id="exportFTPPW" onfocus="this.select()"><br>\
</td></tr></table>\
FTP path/filename<br>\
<input type="text" id="exportFTPFilename" onfocus="this.select()"><br>\
</div><!--panel-->\
\
<!-- notes -->\
notes<br>\
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
\
<!-- list of tiddlers -->\
<table><tr align="left"><td>\
select:\
<a href="JavaScript:;" id="exportSelectAll"\
onclick="onClickExportButton(this)" title="select all tiddlers">\
all </a>\
<a href="JavaScript:;" id="exportSelectChanges"\
onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\
changes </a> \
<a href="JavaScript:;" id="exportSelectOpened"\
onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\
opened </a> \
<a href="JavaScript:;" id="exportToggleFilter"\
onclick="onClickExportButton(this)" title="show/hide selection filter">\
filter </a> \
</td><td align="right">\
<a href="JavaScript:;" id="exportListSmaller"\
onclick="onClickExportButton(this)" title="reduce list size">\
– </a>\
<a href="JavaScript:;" id="exportListLarger"\
onclick="onClickExportButton(this)" title="increase list size">\
+ </a>\
</td></tr></table>\
<select id="exportList" multiple size="10" style="margin-bottom:5px;"\
onchange="refreshExportList(this.selectedIndex)">\
</select><br>\
</div><!--box-->\
\
<!-- selection filter -->\
<div id="exportFilterPanel" style="display:none">\
<table><tr align="left"><td>\
selection filter\
</td><td align="right">\
<a href="JavaScript:;" id="exportHideFilter"\
onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\
</td></tr></table>\
<div class="box">\
<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
onclick="exportShowFilterFields(this)"> starting date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
<select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\
<option value="0">today</option>\
<option value="1">yesterday</option>\
<option value="7">a week ago</option>\
<option value="30">a month ago</option>\
<option value="site">SiteDate</option>\
<option value="file">file date</option>\
<option value="other">other (mm/dd/yyyy hh:mm)</option>\
</select>\
</td><td width="50%">\
<input type="text" id="exportStartDate" onfocus="this.select()"\
onchange="document.getElementById(\'exportFilterStartBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
onclick="exportShowFilterFields(this)"> ending date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
<select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\
<option value="0">today</option>\
<option value="1">yesterday</option>\
<option value="7">a week ago</option>\
<option value="30">a month ago</option>\
<option value="site">SiteDate</option>\
<option value="file">file date</option>\
<option value="other">other (mm/dd/yyyy hh:mm)</option>\
</select>\
</td><td width="50%">\
<input type="text" id="exportEndDate" onfocus="this.select()"\
onchange="document.getElementById(\'exportFilterEndBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id=exportFilterTags value="1"\
onclick="exportShowFilterFields(this)"> match tags<br>\
<input type="text" id="exportTags" onfocus="this.select()">\
<input type="checkbox" class="chk" id=exportFilterText value="1"\
onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\
<input type="text" id="exportText" onfocus="this.select()">\
</div> <!--box-->\
</div> <!--panel-->\
\
<!-- action buttons -->\
<div style="text-align:center">\
<input type=button class="btn3" onclick="onClickExportButton(this)"\
id="exportFilter" value="apply filter">\
<input type=button class="btn3" onclick="onClickExportButton(this)"\
id="exportStart" value="export tiddlers">\
<input type=button class="btn3" onclick="onClickExportButton(this)"\
id="exportClose" value="close">\
</div><!--center-->\
';
//}}}
// // initialize interface
// // exportShowPanel(which)
//{{{
function exportShowPanel(which) {
var index=0; var panel='exportLocalPanel';
switch (which) {
case 'file:':
case undefined:
index=0; panel='exportLocalPanel'; break;
case 'http:':
index=1; panel='exportHTTPPanel'; break;
case 'https:':
index=2; panel='exportHTTPPanel'; break;
case 'ftp:':
index=3; panel='exportFTPPanel'; break;
default:
alert("Sorry, export to "+which+" is not yet available");
break;
}
exportInitPanel(which);
document.getElementById('exportTo').selectedIndex=index;
document.getElementById('exportLocalPanel').style.display='none';
document.getElementById('exportHTTPPanel').style.display='none';
document.getElementById('exportFTPPanel').style.display='none';
document.getElementById(panel).style.display='block';
}
//}}}
// // exportInitPanel(which)
//{{{
function exportInitPanel(which) {
switch (which) {
case "file:": // LOCAL EXPORT PANEL: file/path:
// ** no init - security issues in IE **
break;
case "http:": // WEB EXPORT PANEL
case "https:": // SECURE WEB EXPORT PANEL
// url
if (store.tiddlerExists("unawiki_download")) {
var theURL=store.getTiddlerText("unawiki_download");
theURL=theURL.replace(/\[\[download\|/,'').replace(/\]\]/,'');
var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";
var theHost=store.getTiddlerText(title);
if (!theHost || !theHost.length) theHost=document.location.host;
if (!theHost || !theHost.length) theHost=title;
}
// server script/params
var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";
var theHost=store.getTiddlerText(title);
if (!theHost || !theHost.length) theHost=document.location.host;
if (!theHost || !theHost.length) theHost=title;
// get POST
var title=(store.tiddlerExists("unawiki_post"))?"unawiki_post":"SitePost";
var thePost=store.getTiddlerText(title);
if (!thePost || !thePost.length) thePost="/"+title;
// get PARAMS
var title=(store.tiddlerExists("unawiki_params"))?"unawiki_params":"SiteParams";
var theParams=store.getTiddlerText(title);
if (!theParams|| !theParams.length) theParams=title;
var serverURL = which+"//"+theHost+thePost+"?"+theParams;
document.getElementById("exportHTTPServerURL").value=serverURL;
// get NOTIFY
var theAddresses=store.getTiddlerText("SiteNotify");
if (!theAddresses|| !theAddresses.length) theAddresses="SiteNotify";
document.getElementById("exportNotifyTo").value=theAddresses;
break;
case "ftp:": // FTP EXPORT PANEL
// host
var siteHost=store.getTiddlerText("SiteHost");
if (!siteHost || !siteHost.length) siteHost=document.location.host;
if (!siteHost || !siteHost.length) siteHost="SiteHost";
document.getElementById("exportFTPHost").value=siteHost;
// username
var siteID=store.getTiddlerText("SiteID");
if (!siteID || !siteID.length) siteID=config.options.txtUserName;
document.getElementById("exportFTPID").value=siteID;
// password
document.getElementById("exportFTPPW").value="";
// file/path
document.getElementById("exportFTPFilename").value="";
break;
}
}
//}}}
// // exportInitFilter()
//{{{
function exportInitFilter() {
// start date
document.getElementById("exportFilterStart").checked=false;
document.getElementById("exportStartDate").value="";
// end date
document.getElementById("exportFilterEnd").checked=false;
document.getElementById("exportEndDate").value="";
// tags
document.getElementById("exportFilterTags").checked=false;
document.getElementById("exportTags").value="";
// text
document.getElementById("exportFilterText").checked=false;
document.getElementById("exportText").value="";
// show/hide filter input fields
exportShowFilterFields();
}
//}}}
// // exportShowFilterFields(which)
//{{{
function exportShowFilterFields(which) {
var show;
show=document.getElementById('exportFilterStart').checked;
document.getElementById('exportFilterStartBy').style.display=show?"block":"none";
document.getElementById('exportStartDate').style.display=show?"block":"none";
var val=document.getElementById('exportFilterStartBy').value;
document.getElementById('exportStartDate').value
=getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);
if (which && (which.id=='exportFilterStartBy') && (val=='other'))
document.getElementById('exportStartDate').focus();
show=document.getElementById('exportFilterEnd').checked;
document.getElementById('exportFilterEndBy').style.display=show?"block":"none";
document.getElementById('exportEndDate').style.display=show?"block":"none";
var val=document.getElementById('exportFilterEndBy').value;
document.getElementById('exportEndDate').value
=getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);
if (which && (which.id=='exportFilterEndBy') && (val=='other'))
document.getElementById('exportEndDate').focus();
show=document.getElementById('exportFilterTags').checked;
document.getElementById('exportTags').style.display=show?"block":"none";
show=document.getElementById('exportFilterText').checked;
document.getElementById('exportText').style.display=show?"block":"none";
}
//}}}
// // onClickExportButton(which): control interactions
//{{{
function onClickExportButton(which)
{
// DEBUG alert(which.id);
var theList=document.getElementById('exportList'); if (!theList) return;
var count = 0;
var total = store.getTiddlers('title').length;
switch (which.id)
{
case 'exportFilter':
count=filterExportList();
var panel=document.getElementById('exportFilterPanel');
if (count==-1) { panel.style.display='block'; break; }
document.getElementById("exportStart").disabled=(count==0);
clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));
if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
break;
case 'exportStart':
exportTiddlers();
break;
case 'exportHideFilter':
case 'exportToggleFilter':
var panel=document.getElementById('exportFilterPanel')
panel.style.display=(panel.style.display=='block')?'none':'block';
break;
case 'exportSelectChanges':
var lastmod=new Date(document.lastModified);
for (var t = 0; t < theList.options.length; t++) {
if (theList.options[t].value=="") continue;
var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
theList.options[t].selected=(tiddler.modified>lastmod);
count += (tiddler.modified>lastmod)?1:0;
}
document.getElementById("exportStart").disabled=(count==0);
clearMessage(); displayMessage(formatExportMessage(count,total));
if (count==0) alert("There are no unsaved changes");
break;
case 'exportSelectAll':
for (var t = 0; t < theList.options.length; t++) {
if (theList.options[t].value=="") continue;
theList.options[t].selected=true;
count += 1;
}
document.getElementById("exportStart").disabled=(count==0);
clearMessage(); displayMessage(formatExportMessage(count,count));
break;
case 'exportSelectOpened':
for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
var tiddlerDisplay = document.getElementById("tiddlerDisplay"); // for TW2.1-
if (!tiddlerDisplay) tiddlerDisplay = document.getElementById("storyDisplay"); // for TW2.2+
for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
for (var i = 0; i < theList.options.length; i++) {
if (theList.options[i].value!=tiddler) continue;
theList.options[i].selected=true; count++; break;
}
}
document.getElementById("exportStart").disabled=(count==0);
clearMessage(); displayMessage(formatExportMessage(count,total));
if (count==0) alert("There are no tiddlers currently opened");
break;
case 'exportListSmaller': // decrease current listbox size
var min=5;
theList.size-=(theList.size>min)?1:0;
break;
case 'exportListLarger': // increase current listbox size
var max=(theList.options.length>25)?theList.options.length:25;
theList.size+=(theList.size<max)?1:0;
break;
case 'exportClose':
document.getElementById('exportPanel').style.display='none';
break;
}
}
//}}}
// // list display
//{{{
function formatExportMessage(count,total)
{
var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";
txt += (count==0)?"none":(count==total)?"all":count;
txt += " selected for export";
return txt;
}
function refreshExportList(selectedIndex)
{
var theList = document.getElementById("exportList");
var sort;
if (!theList) return;
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) sort='modified';
if (selectedIndex==1) sort='title';
if (selectedIndex==2) sort='modified';
if (selectedIndex==3) sort='modifier';
if (selectedIndex==4) sort='tags';
// unselect headings and count number of tiddlers actually selected
for (var t=0,count=0; t < theList.options.length; t++) {
if (!theList.options[t].selected) continue;
if (theList.options[t].value!="")
count++;
else { // if heading is selected, deselect it, and then select and count all in section
theList.options[t].selected=false;
for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
theList.options[t].selected=true;
count++;
}
}
}
// disable "export" button if no tiddlers selected
document.getElementById("exportStart").disabled=(count==0);
// show selection count
var tiddlers = store.getTiddlers('title');
if (theList.options.length) { clearMessage(); displayMessage(formatExportMessage(count,tiddlers.length)); }
// if a [command] item, reload list... otherwise, no further refresh needed
if (selectedIndex>4) return;
// clear current list contents
while (theList.length > 0) { theList.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
theList.options[i++]=
new Option(tiddlers.length+" tiddlers in document", "",false,false);
theList.options[i++]=
new Option(((sort=="title" )?">":indent)+' [by title]', "",false,false);
theList.options[i++]=
new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
theList.options[i++]=
new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
theList.options[i++]=
new Option(((sort=="tags" )?">":indent)+' [by tags]', "",false,false);
// output the tiddler list
switch(sort)
{
case "title":
for(var t = 0; t < tiddlers.length; t++)
theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
break;
case "modifier":
case "modified":
var tiddlers = store.getTiddlers(sort);
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
var lastSection = "";
for(var t = 0; t < tiddlers.length; t++)
{
var tiddler = tiddlers[t];
var theSection = "";
if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
if (sort=="modifier") theSection=tiddler.modifier;
if (theSection != lastSection)
{
theList.options[i++] = new Option(theSection,"",false,false);
lastSection = theSection;
}
theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
}
break;
case "tags":
var theTitles = {}; // all tiddler titles, hash indexed by tag value
var theTags = new Array();
for(var t=0; t<tiddlers.length; t++) {
var title=tiddlers[t].title;
var tags=tiddlers[t].tags;
if (!tags || !tags.length) {
if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
theTitles["untagged"].push(title);
}
else for(var s=0; s<tags.length; s++) {
if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
theTitles[tags[s]].push(title);
}
}
theTags.sort();
for(var tagindex=0; tagindex<theTags.length; tagindex++) {
var theTag=theTags[tagindex];
theList.options[i++]=new Option(theTag,"",false,false);
for(var t=0; t<theTitles[theTag].length; t++)
theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
theList.selectedIndex=selectedIndex; // select current control item
}
//}}}
// // list filtering
//{{{
function getFilterDate(val,id)
{
var result=0;
switch (val) {
case 'site':
var timestamp=store.getTiddlerText("SiteDate");
if (!timestamp) timestamp=document.lastModified;
result=new Date(timestamp);
break;
case 'file':
result=new Date(document.lastModified);
break;
case 'other':
result=new Date(document.getElementById(id).value);
break;
default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
var oneday=86400000;
if (id=='exportStartDate')
result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
else
result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
break;
}
// DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\nnow="+now);
return result;
}
function filterExportList()
{
var theList = document.getElementById("exportList"); if (!theList) return -1;
var filterStart=document.getElementById("exportFilterStart").checked;
var val=document.getElementById("exportFilterStartBy").value;
var startDate=getFilterDate(val,'exportStartDate');
var filterEnd=document.getElementById("exportFilterEnd").checked;
var val=document.getElementById("exportFilterEndBy").value;
var endDate=getFilterDate(val,'exportEndDate');
var filterTags=document.getElementById("exportFilterTags").checked;
var tags=document.getElementById("exportTags").value;
var filterText=document.getElementById("exportFilterText").checked;
var text=document.getElementById("exportText").value;
if (!(filterStart||filterEnd||filterTags||filterText)) {
alert("Please set the selection filter");
document.getElementById('exportFilterPanel').style.display="block";
return -1;
}
if (filterStart&&filterEnd&&(startDate>endDate)) {
var msg="starting date/time:\n"
msg+=startDate.toLocaleString()+"\n";
msg+="is later than ending date/time:\n"
msg+=endDate.toLocaleString()
alert(msg);
return -1;
}
// scan list and select tiddlers that match all applicable criteria
var total=0;
var count=0;
for (var i=0; i<theList.options.length; i++) {
// get item, skip non-tiddler list items (section headings)
var opt=theList.options[i]; if (opt.value=="") continue;
// get tiddler, skip missing tiddlers (this should NOT happen)
var tiddler=store.getTiddler(opt.value); if (!tiddler) continue;
var sel=true;
if ( (filterStart && tiddler.modified<startDate)
|| (filterEnd && tiddler.modified>endDate)
|| (filterTags && !matchTags(tiddler,tags))
|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
sel=false;
opt.selected=sel;
count+=sel?1:0;
total++;
}
return count;
}
//}}}
//{{{
function matchTags(tiddler,cond)
{
if (!cond||!cond.trim().length) return false;
// build a regex of all tags as a big-old regex that
// OR's the tags together (tag1|tag2|tag3...) in length order
var tgs = store.getTags();
if ( tgs.length == 0 ) return results ;
var tags = tgs.sort( function(a,b){return (a[0].length<b[0].length)-(a[0].length>b[0].length);});
var exp = "(" + tags.join("|") + ")" ;
exp = exp.replace( /(,[\d]+)/g, "" ) ;
var regex = new RegExp( exp, "ig" );
// build a string such that an expression that looks like this: tag1 AND tag2 OR NOT tag3
// turns into : /tag1/.test(...) && /tag2/.test(...) || ! /tag2/.test(...)
cond = cond.replace( regex, "/$1\\|/.test(tiddlerTags)" );
cond = cond.replace( /\sand\s/ig, " && " ) ;
cond = cond.replace( /\sor\s/ig, " || " ) ;
cond = cond.replace( /\s?not\s/ig, " ! " ) ;
// if a boolean uses a tag that doesn't exist - it will get left alone
// (we only turn existing tags into actual tests).
// replace anything that wasn't found as a tag, AND, OR, or NOT with the string "false"
// if the tag doesn't exist then /tag/.test(...) will always return false.
cond = cond.replace( /(\s|^)+[^\/\|&!][^\s]*/g, "false" ) ;
// make a string of the tags in the tiddler and eval the 'cond' string against that string
// if it's TRUE then the tiddler qualifies!
var tiddlerTags = (tiddler.tags?tiddler.tags.join("|"):"")+"|" ;
try { if ( eval( cond ) ) return true; }
catch( e ) { displayMessage("Error in tag filter '" + e + "'" ); }
return false;
}
//}}}
// // output data formatting
// // exportHeader(format)
//{{{
function exportHeader(format)
{
switch (format) {
case "TW": return exportTWHeader();
case "DIV": return exportDIVHeader();
case "XML": return exportXMLHeader();
}
}
//}}}
// // exportFooter(format)
//{{{
function exportFooter(format)
{
switch (format) {
case "TW": return exportDIVFooter();
case "DIV": return exportDIVFooter();
case "XML": return exportXMLFooter();
}
}
//}}}
// // exportTWHeader()
//{{{
function exportTWHeader()
{
// Get the URL of the document
var originalPath = document.location.href;
// Check we were loaded from a file URL
if(originalPath.substr(0,5) != "file:")
{ alert(config.messages.notFileUrlError); return; }
// Remove any location part of the URL
var hashPos = originalPath.indexOf("#"); if(hashPos != -1) originalPath = originalPath.substr(0,hashPos);
// Convert to a native file format assuming
// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
var localPath;
if(originalPath.charAt(9) == ":") // pc local file
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file:///") == 0) // mac/unix local file
localPath = unescape(originalPath.substr(7));
else if(originalPath.indexOf("file:/") == 0) // mac/unix local file
localPath = unescape(originalPath.substr(5));
else // pc network file
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
// Load the original file
var original = loadFile(localPath);
if(original == null)
{ alert(config.messages.cantSaveError); return; }
// Locate the storeArea div's
var posOpeningDiv = original.indexOf(startSaveArea);
var posClosingDiv = original.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1))
{ alert(config.messages.invalidFileError.format([localPath])); return; }
return original.substr(0,posOpeningDiv+startSaveArea.length)
}
//}}}
// // exportDIVHeader()
//{{{
function exportDIVHeader()
{
var out=[];
var now = new Date();
var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
var twver = version.major+"."+version.minor+"."+version.revision;
var pver = version.extensions.exportTiddlers.major+"."
+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
out.push("<html><body>");
out.push("<style type=\"text/css\">");
out.push("#storeArea {display:block;margin:1em;}");
out.push("#storeArea div");
out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");
out.push("#javascriptWarning");
out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");
out.push("</style>");
out.push("<div id=\"javascriptWarning\">");
out.push("TiddlyWiki export file<br>");
out.push("Source"+": <b>"+convertUnicodeToUTF8(document.location.href)+"</b><br>");
out.push("Title: <b>"+title+"</b><br>");
out.push("Subtitle: <b>"+subtitle+"</b><br>");
out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");
out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");
out.push("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(regexpNewLine,"<br>")+"</pre>");
out.push("</div>");
out.push("<div id=\"storeArea\">");
return out;
}
//}}}
// // exportDIVFooter()
//{{{
function exportDIVFooter()
{
var out=[];
out.push("</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>");
return out;
}
//}}}
// // exportXMLHeader()
//{{{
function exportXMLHeader()
{
var out=[];
var now = new Date();
var u = store.getTiddlerText("SiteUrl",null);
var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
var twver = version.major+"."+version.minor+"."+version.revision;
var pver = version.extensions.exportTiddlers.major+"."
+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
out.push("<" + "?xml version=\"1.0\"?" + ">");
out.push("<rss version=\"2.0\">");
out.push("<channel>");
out.push("<title>" + title + "</title>");
if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");
out.push("<description>" + subtitle + "</description>");
out.push("<language>en-us</language>");
out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");
out.push("<pubDate>" + now.toGMTString() + "</pubDate>");
out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");
out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");
return out;
}
//}}}
// // exportXMLFooter()
//{{{
function exportXMLFooter()
{
var out=[];
out.push("</channel></rss>");
return out;
}
//}}}
// // exportData()
//{{{
function exportData(theList,theFormat)
{
// scan export listbox and collect DIVs or XML for selected tiddler content
var out=[];
for (var i=0; i<theList.options.length; i++) {
// get item, skip non-selected items and section headings
var opt=theList.options[i]; if (!opt.selected||(opt.value=="")) continue;
// get tiddler, skip missing tiddlers (this should NOT happen)
var thisTiddler=store.getTiddler(opt.value); if (!thisTiddler) continue;
if (theFormat=="TW") out.push(convertUnicodeToUTF8(thisTiddler.saveToDiv()));
if (theFormat=="DIV") out.push(convertUnicodeToUTF8(thisTiddler.title+"\n"+thisTiddler.saveToDiv()));
if (theFormat=="XML") out.push(convertUnicodeToUTF8(thisTiddler.saveToRss(store.getTiddlerText("SiteUrl",""))));
}
return out;
}
//}}}
// // exportTiddlers(): output selected data to local or server
//{{{
function exportTiddlers()
{
var theList = document.getElementById("exportList"); if (!theList) return;
// get the export settings
var theProtocol = document.getElementById("exportTo").value;
var theFormat = document.getElementById("exportFormat").value;
// assemble output: header + tiddlers + footer
var theData=exportData(theList,theFormat);
var count=theData.length;
var out=[]; var txt=out.concat(exportHeader(theFormat),theData,exportFooter(theFormat)).join("\n");
var msg="";
switch (theProtocol) {
case "file:":
var theTarget = document.getElementById("exportFilename").value.trim();
if (!theTarget.length) msg = "A local path/filename is required\n";
if (!msg && saveFile(theTarget,txt))
msg=count+" tiddler"+((count!=1)?"s":"")+" exported to local file";
else if (!msg)
msg+="An error occurred while saving to "+theTarget;
break;
case "http:":
case "https:":
var theTarget = document.getElementById("exportHTTPServerURL").value.trim();
if (!theTarget.length) msg = "A server URL is required\n";
if (document.getElementById('exportNotify').checked)
theTarget+="¬ify="+encodeURIComponent(document.getElementById('exportNotifyTo').value);
if (document.getElementById('exportNotes').value.trim().length)
theTarget+="¬es="+encodeURIComponent(document.getElementById('exportNotes').value);
if (!msg && exportPost(theTarget+encodeURIComponent(txt)))
msg=count+" tiddler"+((count!=1)?"s":"")+" exported to "+theProtocol+" server";
else if (!msg)
msg+="An error occurred while saving to "+theTarget;
break;
case "ftp:":
default:
msg="Sorry, export to "+theLocation+" is not yet available";
break;
}
clearMessage(); displayMessage(msg,theTarget);
}
//}}}
// // exportPost(url): cross-domain post uses hidden iframe to submit url and capture responses
//{{{
function exportPost(url)
{
var f=document.getElementById("exportFrame"); if (f) document.body.removeChild(f);
f=document.createElement("iframe"); f.id="exportFrame";
f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
document.body.appendChild(f);
var d=f.document;
if (f.contentDocument) d=f.contentDocument; // For NS6
else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
d.location.replace(url);
return true;
}
//}}}
// // promptForFilename(msg,path,file) uses platform/browser specific functions to get local filespec
//{{{
function promptForExportFilename(here)
{
var msg=here.title; // use tooltip as dialog box message
var path=getLocalPath(document.location.href);
var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\");
if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
var file=config.macros.exportTiddlers.newdefault;
var result="";
if(window.Components) { // moz
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
picker.init(window, msg, nsIFilePicker.modeSave);
var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
thispath.initWithPath(path);
picker.displayDirectory=thispath;
picker.defaultExtension='html';
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XP only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
s.FilterIndex=3; // default to HTML files;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
}
return result;
}
//}}}
The Household Activity Pattern Problem is a mathematical programming formulation due to [[Recker|http://repositories.cdlib.org/cgi/viewcontent.cgi?article=1052&context=itsirvine/casa]] of the problem faced by a household (or arbitrary social group) to jointly perform a set of activities given a stable of vehicles to travel through time and space.
[[ITS-Irvine|http://www.its.uci.edu/]] is [[my|Craig Rindt]] employer.
[[Publications]]
[[Projects]]
[[Photos|http://parsons.its.uci.edu/~crindt/photos/]]
[[CV|http://parsons.its.uci.edu/~crindt/professional/cv/Craig_Rindt_CV-Long.xhtml]]
With apologies to the TiddlyWiki team, NoteBlog is my term for a "reusable non-linear personal web notebook".
PasswordOptionPlugin extends the core Options with a non encrypted password type.
Notice:
*How a style can be specified for a specific option in StyleSheet
----
Test Password: <<option pasPassword myPasOptionInput >>
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
These are the various projects I am or have worked on.
Representative publications are available on my [[CV|http://parsons.its.uci.edu/~crindt/professional/cv]]
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<upload>><<slider chkSliderOptionsPanel OptionsPanel 'options ยป' 'Change TiddlyWiki advanced options'>> <<exportTiddlers>>
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Version|2.3.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <<br>>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler(), Story.prototype.displayTiddlers()|
|Description|Display tiddlers one at a time with automatic update of URL (permalink). Also, options to always open tiddlers at top/bottom of page|
Normally, as you click on the links in TiddlyWiki, more and more tiddlers are displayed on the page. The order of this tiddler display depends upon when and where you have clicked. Some people like this non-linear method of reading the document, while others have reported that when many tiddlers have been opened, it can get somewhat confusing.
!!!!!Usage
<<<
SinglePageMode allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time. When SinglePageMode is enabled, the title of the current tiddler is automatically displayed in the browser window's titlebar and the browser's location URL is updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler.
Even when SinglePageMode is disabled (i.e., displaying multiple tiddlers is permitted), you can reduce the potential for confusion by enable TopOfPageMode, which forces tiddlers to always open at the top of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
When installed, this plugin automatically adds checkboxes in the AdvancedOptions tiddler so you can enable/disable the plugin behavior. For convenience, these checkboxes are also included here:
<<option chkSinglePageMode>> Display one tiddler at a time
<<option chkTopOfPageMode>> Always open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Always open tiddlers at the bottom of the page
//(note: if both settings are selected, "top of page" is used)//
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''SinglePageModePlugin'' (tagged with <<tag systemConfig>>)
^^documentation and javascript for SinglePageMode handling^^
When installed, this plugin automatically adds checkboxes in the ''shadow'' AdvancedOptions tiddler so you can enable/disable this behavior. However, if you have customized your AdvancedOptions, you will need to ''manually add these checkboxes to your customized tiddler.''
<<<
!!!!!Revision History
<<<
''2007.03.03 [2.3.1]'' fix typo when adding BPM option to AdvancedOptions (prevented checkbox from appearing)
''2007.03.03 [2.3.0]'' added support for BottomOfPageMode (BPM) based on request from DaveGarbutt
''2007.02.06 [2.2.3]'' in Story.prototype.displayTiddler(), use convertUnicodeToUTF8() for correct I18N string handling when creating URL hash string from tiddler title (based on bug report from BidiX)
''2007.01.08 [2.2.2]'' use apply() to invoke hijacked core functions
''2006.07.04 [2.2.1]'' in hijack for displayTiddlers(), suspend TPM as well as SPM so that DefaultTiddlers displays in the correct order.
''2006.06.01 [2.2.0]'' added chkTopOfPageMode (TPM) handling
''2006.02.04 [2.1.1]'' moved global variable declarations to config.* to avoid FireFox 1.5.0.1 crash bug when assigning to globals
''2005.12.27 [2.1.0]'' hijack displayTiddlers() so that SPM can be suspended during startup while displaying the DefaultTiddlers (or #hash list). Also, corrected initialization for undefined SPM flag to "false", so default behavior is to display multiple tiddlers
''2005.12.27 [2.0.0]'' Update for TW2.0
''2005.11.24 [1.1.2]'' When the back and forward buttons are used, the page now changes to match the URL. Based on code added by Clint Checketts
''2005.10.14 [1.1.1]'' permalink creation now calls encodeTiddlyLink() to handle tiddler titles with spaces in them
''2005.10.14 [1.1.0]'' added automatic setting of window title and location bar ('auto-permalink'). feature suggestion by David Dickens.
''2005.10.09 [1.0.1]'' combined documentation and code in a single tiddler
''2005.08.15 [1.0.0]'' Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].
Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageMode= {major: 2, minor: 3, revision: 1, date: new Date(2007,3,3)};
if (config.options.chkSinglePageMode==undefined) config.options.chkSinglePageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSinglePageMode>> Display one tiddler at a time";
if (config.options.chkTopOfPageMode==undefined) config.options.chkTopOfPageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkTopOfPageMode>> Always open tiddlers at the top of the page";
if (config.options.chkBottomOfPageMode==undefined) config.options.chkBottomOfPageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkBottomOfPageMode>> Always open tiddlers at the bottom of the page";
config.SPMTimer = 0;
config.lastURL = window.location.hash;
function checkLastURL()
{
if (!config.options.chkSinglePageMode)
{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
if (config.lastURL == window.location.hash)
return;
var tiddlerName = convertUTF8ToUnicode(decodeURI(window.location.hash.substr(1)));
tiddlerName=tiddlerName.replace(/\[\[/,"").replace(/\]\]/,""); // strip any [[ ]] bracketing
if (tiddlerName.length) story.displayTiddler(null,tiddlerName,1,null,null);
}
if (Story.prototype.SPM_coreDisplayTiddler==undefined) Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
if (config.options.chkSinglePageMode) {
window.location.hash = encodeURIComponent(convertUnicodeToUTF8(String.encodeTiddlyLink(title)));
config.lastURL = window.location.hash;
document.title = wikifyPlain("SiteTitle") + " - " + title;
story.closeAllTiddlers();
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
if (config.options.chkTopOfPageMode) { story.closeTiddler(title); srcElement=null; }
else if (config.options.chkBottomOfPageMode) { story.closeTiddler(title); srcElement="bottom"; }
this.SPM_coreDisplayTiddler.apply(this,arguments);
if (config.options.chkTopOfPageMode) window.scrollTo(0,0); // make sure top of page is visible
else if (config.options.chkBottomOfPageMode) {
var display=document.getElementById("tiddlerDisplay"); // for TW2.1-
if (!display) var display=document.getElementById("storyDisplay"); // for TW2.2+
window.scrollTo(0,ensureVisible(display.lastChild)); // make sure last tiddler is visible
}
}
if (Story.prototype.SPM_coreDisplayTiddlers==undefined) Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function(srcElement,titles,template,unused1,unused2,animate,slowly)
{
// suspend single-page mode (and/or top/bottom display options) when showing multiple tiddlers
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
this.SPM_coreDisplayTiddlers.apply(this,arguments);
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
}
//}}}
a static homepage for obtaining information about me...
http://parsons.its.uci.edu/~crindt/index.html
Tiddlers with this tag will always be displayed on the site.
<<timeline better:true onlyTag:Blog sortBy:created maxDays:7 maxEntries:30>>
/***
| Name|TagglyTaggingPlugin|
| Description|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
| Version|3.0 ($Rev: 2101 $)|
| Date|$Date: 2007-04-20 00:24:20 +1000 (Fri, 20 Apr 2007) $|
| Source|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
| Author|Simon Baird <simon.baird@gmail.com>|
| License|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{
config.taggly = {
// for translations
lingo: {
labels: {
asc: "\u2191", // down arrow
desc: "\u2193", // up arrow
title: "title",
modified: "modified",
created: "created",
show: "+",
hide: "-",
normal: "normal",
group: "group",
commas: "commas",
sitemap: "sitemap",
numCols: "cols\u00b1", // plus minus sign
label: "Tagged as '%0':",
excerpts: "excerpts",
noexcerpts: "no excerpts"
},
tooltips: {
title: "Click to sort by title",
modified: "Click to sort by modified date",
created: "Click to sort by created date",
show: "Click to show tagging list",
hide: "Click to hide tagging list",
normal: "Click to show a normal ungrouped list",
group: "Click to show list grouped by tag",
sitemap: "Click to show a sitemap style list",
commas: "Click to show a comma separated list",
numCols: "Click to change number of columns"
}
},
config: {
showTaggingCounts: true,
listOpts: {
// the first one will be the default
sortBy: ["title","modified","created"],
sortOrder: ["asc","desc"],
hideState: ["show","hide"],
listMode: ["normal","group","sitemap","commas"],
numCols: ["1","2","3","4","5","6"],
excerpts: ["noexcerpts","excerpts"]
},
valuePrefix: "taggly.",
excludeTags: ["excludeLists","excludeTagging"],
excerptSize: 50,
excerptMarker: "/%"+"%/"
},
getTagglyOpt: function(title,opt) {
var val = store.getValue(title,this.config.valuePrefix+opt);
return val ? val : this.config.listOpts[opt][0];
},
setTagglyOpt: function(title,opt,value) {
if (!store.tiddlerExists(title))
// create it silently
store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),null);
// if value is default then remove it to save space
return store.setValue(title,
this.config.valuePrefix+opt,
value == this.config.listOpts[opt][0] ? null : value);
},
getNextValue: function(title,opt) {
var current = this.getTagglyOpt(title,opt);
var pos = this.config.listOpts[opt].indexOf(current);
// a little usability enhancement. actually it doesn't work right for grouped or sitemap
var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);
var newPos = (pos + 1) % limit;
return this.config.listOpts[opt][newPos];
},
toggleTagglyOpt: function(title,opt) {
var newVal = this.getNextValue(title,opt);
this.setTagglyOpt(title,opt,newVal);
},
createListControl: function(place,title,type) {
var lingo = config.taggly.lingo;
var label;
var tooltip;
var onclick;
if ((type == "title" || type == "modified" || type == "created")) {
// "special" controls. a little tricky. derived from sortOrder and sortBy
label = lingo.labels[type];
tooltip = lingo.tooltips[type];
if (this.getTagglyOpt(title,"sortBy") == type) {
label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
onclick = function() {
config.taggly.toggleTagglyOpt(title,"sortOrder");
return false;
}
}
else {
onclick = function() {
config.taggly.setTagglyOpt(title,"sortBy",type);
config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
return false;
}
}
}
else {
// "regular" controls, nice and simple
label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
onclick = function() {
config.taggly.toggleTagglyOpt(title,type);
return false;
}
}
// hide button because commas don't have columns
if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
},
makeColumns: function(orig,numCols) {
var listSize = orig.length;
var colSize = listSize/numCols;
var remainder = listSize % numCols;
var upperColsize = colSize;
var lowerColsize = colSize;
if (colSize != Math.floor(colSize)) {
// it's not an exact fit so..
upperColsize = Math.floor(colSize) + 1;
lowerColsize = Math.floor(colSize);
}
var output = [];
var c = 0;
for (var j=0;j<numCols;j++) {
var singleCol = [];
var thisSize = j < remainder ? upperColsize : lowerColsize;
for (var i=0;i<thisSize;i++)
singleCol.push(orig[c++]);
output.push(singleCol);
}
return output;
},
drawTable: function(place,columns,theClass) {
var newTable = createTiddlyElement(place,"table",null,theClass);
var newTbody = createTiddlyElement(newTable,"tbody");
var newTr = createTiddlyElement(newTbody,"tr");
for (var j=0;j<columns.length;j++) {
var colOutput = "";
for (var i=0;i<columns[j].length;i++)
colOutput += columns[j][i];
var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
wikify(colOutput,newTd);
}
return newTable;
},
createTagglyList: function(place,title) {
switch(this.getTagglyOpt(title,"listMode")) {
case "group": return this.createTagglyListGrouped(place,title); break;
case "normal": return this.createTagglyListNormal(place,title,false); break;
case "commas": return this.createTagglyListNormal(place,title,true); break;
case "sitemap":return this.createTagglyListSiteMap(place,title); break;
}
},
getTaggingCount: function(title) {
// thanks to Doug Edmunds
if (this.config.showTaggingCounts) {
var tagCount = store.getTaggedTiddlers(title).length;
if (tagCount > 0)
return " ("+tagCount+")";
}
return "";
},
getExcerpt: function(inTiddlerTitle,title) {
if (this.getTagglyOpt(inTiddlerTitle,"excerpts") == "excerpts") {
var t = store.getTiddler(title);
if (t) {
var text = t.text.replace(/\n/," ");
var marker = text.indexOf(this.config.excerptMarker);
if (marker != -1) {
return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
}
else if (text.length < this.config.excerptSize) {
return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
}
else {
return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
}
}
}
return "";
},
notHidden: function(t,inTiddler) {
if (typeof t == "string")
t = store.getTiddler(t);
return (!t || !t.tags.containsAny(this.config.excludeTags) ||
(inTiddler && this.config.excludeTags.contains(inTiddler)));
},
// this is for normal and commas mode
createTagglyListNormal: function(place,title,useCommas) {
var list = store.getTaggedTiddlers(title,this.getTagglyOpt(title,"sortBy"));
if (this.getTagglyOpt(title,"sortOrder") == "desc")
list = list.reverse();
var output = [];
var first = true;
for (var i=0;i<list.length;i++) {
if (this.notHidden(list[i],title)) {
var countString = this.getTaggingCount(list[i].title);
var excerpt = this.getExcerpt(title,list[i].title);
if (useCommas)
output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
else
output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");
first = false;
}
}
return this.drawTable(place,
this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
useCommas ? "commas" : "normal");
},
// this is for the "grouped" mode
createTagglyListGrouped: function(place,title) {
var sortBy = this.getTagglyOpt(title,"sortBy");
var sortOrder = this.getTagglyOpt(title,"sortOrder");
var list = store.getTaggedTiddlers(title,sortBy);
if (sortOrder == "desc")
list = list.reverse();
var leftOvers = []
for (var i=0;i<list.length;i++)
leftOvers.push(list[i].title);
var allTagsHolder = {};
for (var i=0;i<list.length;i++) {
for (var j=0;j<list[i].tags.length;j++) {
if (list[i].tags[j] != title) { // not this tiddler
if (this.notHidden(list[i].tags[j],title)) {
if (!allTagsHolder[list[i].tags[j]])
allTagsHolder[list[i].tags[j]] = "";
if (this.notHidden(list[i],title)) {
allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";
leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers
}
}
}
}
}
var allTags = [];
for (var t in allTagsHolder)
allTags.push(t);
var sortHelper = function(a,b) {
if (a == b) return 0;
if (a < b) return -1;
return 1;
};
allTags.sort(function(a,b) {
var tidA = store.getTiddler(a);
var tidB = store.getTiddler(b);
if (sortBy == "title") return sortHelper(a,b);
else if (!tidA && !tidB) return 0;
else if (!tidA) return -1;
else if (!tidB) return +1;
else return sortHelper(tidA[sortBy],tidB[sortBy]);
});
var leftOverOutput = "";
for (var i=0;i<leftOvers.length;i++)
if (this.notHidden(leftOvers[i],title))
leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";
var output = [];
if (sortOrder == "desc")
allTags.reverse();
else if (leftOverOutput != "")
// leftovers first...
output.push(leftOverOutput);
for (var i=0;i<allTags.length;i++)
if (allTagsHolder[allTags[i]] != "")
output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);
if (sortOrder == "desc" && leftOverOutput != "")
// leftovers last...
output.push(leftOverOutput);
return this.drawTable(place,
this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
"grouped");
},
// used to build site map
treeTraverse: function(title,depth,sortBy,sortOrder) {
var list = store.getTaggedTiddlers(title,sortBy);
if (sortOrder == "desc")
list.reverse();
var indent = "";
for (var j=0;j<depth;j++)
indent += "*"
var childOutput = "";
for (var i=0;i<list.length;i++)
if (list[i].title != title)
if (this.notHidden(list[i].title,this.config.inTiddler))
childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder);
if (depth == 0)
return childOutput;
else
return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title) + "\n" + childOutput;
},
// this if for the site map mode
createTagglyListSiteMap: function(place,title) {
this.config.inTiddler = title; // nasty. should pass it in to traverse probably
var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"));
return this.drawTable(place,
this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
"sitemap"
);
},
macros: {
tagglyTagging: {
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var refreshContainer = createTiddlyElement(place,"div");
// do some refresh magic to make it keep the list fresh - thanks Saq
refreshContainer.setAttribute("refresh","macro");
refreshContainer.setAttribute("macroName",macroName);
refreshContainer.setAttribute("title",tiddler.title);
this.refresh(refreshContainer);
},
refresh: function(place) {
var title = place.getAttribute("title");
removeChildren(place);
if (store.getTaggedTiddlers(title).length > 0) {
var lingo = config.taggly.lingo;
config.taggly.createListControl(place,title,"hideState");
if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
createTiddlyElement(place,"span",null,"tagglyLabel",lingo.labels.label.format([title]));
config.taggly.createListControl(place,title,"title");
config.taggly.createListControl(place,title,"modified");
config.taggly.createListControl(place,title,"created");
config.taggly.createListControl(place,title,"listMode");
config.taggly.createListControl(place,title,"excerpts");
config.taggly.createListControl(place,title,"numCols");
config.taggly.createTagglyList(place,title);
}
}
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
" margin-top:0px; padding-top:0.5em; padding-left:2em;",
" margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
" border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active {",
" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryMid]]; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
"/*}}}*/",
""].join("\n"),
init: function() {
merge(config.macros,this.macros);
config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
store.addNotification("TagglyTaggingStyles",refreshStyles);
}
};
config.taggly.init();
//}}}
[[TiddlyWiki|http://www.tiddlywiki.com]] is the "software" used on these personal web pages. It is implemented entirely using client-side javascript and is very cool. If you're reading this right now, your web browser contains my complete blog/wiki (or, as I'm calling it, my [[NoteBlog]]).
UploadPlugin with <<tag UploadService>> extend TiddlyWiki with @@upload@@ and @@save to web@@ commands.
See [[HowToUpload]].
[[Upload]] is :
<<tiddler UploadPluginDoc>>
This form upload any file with an UploadService describe in [[Upload]]
----
<html><center>
<form enctype="multipart/form-data" action="store.php" method="post" target="_blank">
<input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
This file : <input name="userfile" type="file" /><p>
Options* : <input type="text" name="UploadPlugin" size=80 value="backupDir=BACKUP_DIR;uploaddir=UPLOAD_DIR;user=UPLOAD_USER;password=UPLOAD_PASSWORD;debug=0;" /><p>
<input type="submit" value="Upload" />
</form></center>
</html>
----
* Substitute BACKUP_DIR, UPLOAD_DIR, UPLOAD_USER and UPLOAD_PASSWORD with your values. See UploadPlugin for option details.
For security reason, don't save your password in a tiddler.
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 11/06/2007 10:58:39 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store-tw.php|file:///home/crindt/Desktop/noteblog/[http://parsons.its.uci.edu/~crindt/store-tw.php]] | [noteblog | [[[index.html | file:///home/crindt/Desktop/noteblog/[http://parsons.its.uci.edu/~crindt/[noteblog/[index.html]] | [noteblog/backup |
| 11/06/2007 10:58:55 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store-tw.php|http://parsons.its.uci.edu/~crindt/store-tw.php]] | noteblog | [[index.html | http://parsons.its.uci.edu/~crindt/noteblog/index.html]] | noteblog/backup | ok |
| 11/06/2007 10:59:02 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store-tw.php|file:///home/crindt/Desktop/noteblog/[http://parsons.its.uci.edu/~crindt/store-tw.php]] | [noteblog | [[[index.html | file:///home/crindt/Desktop/noteblog/[http://parsons.its.uci.edu/~crindt/[noteblog/[index.html]] | [noteblog/backup |
| 11/06/2007 10:59:19 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store-tw.php|http://parsons.its.uci.edu/~crindt/store-tw.php]] | noteblog | [[index.html | http://parsons.its.uci.edu/~crindt/noteblog/index.html]] | noteblog/backup | ok |
| 11/06/2007 11:29:57 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store.php|file:///home/crindt/Desktop/noteblog/store.php]] | . | [[index.html | file:///home/crindt/Desktop/noteblog/index.html]] | noteblog/backup |
| 11/06/2007 11:30:08 | Craig Rindt | [[noteblog.html|file:///home/crindt/Desktop/noteblog/noteblog.html]] | [[store-tw.php|http://parsons.its.uci.edu/~crindt/store-tw.php]] | noteblog | [[index.html | http://parsons.its.uci.edu/~crindt/noteblog/index.html]] | noteblog/backup | ok |
| 15/06/2007 09:01:08 | Craig Rindt | [[index.html|file:///home/crindt/public_html/index.html]] | [[store.php|file:///home/crindt/public_html/store.php]] | . | [[index.html | file:///home/crindt/public_html/index.html]] | noteblog/backup |
| 15/06/2007 09:02:52 | Craig Rindt | [[index.html|file:///home/crindt/public_html/index.html]] | [[store.php|file:///home/crindt/public_html/store.php]] | . | [[index.html | file:///home/crindt/public_html/index.html]] | noteblog/backup |
| 15/06/2007 09:09:28 | Craig Rindt | [[index.html|file:///home/crindt/public_html/index.html]] | [[store.php|file:///home/crindt/public_html/store.php]] | . | [[index.html | file:///home/crindt/public_html/index.html]] | noteblog/backup |
| 15/06/2007 09:10:20 | Craig Rindt | [[index.html|file:///home/crindt/public_html/index.html]] | [[store-tw.php|http://parsons.its.uci.edu/~crindt/store-tw.php]] | . | [[index.html | http://parsons.its.uci.edu/~crindt/index.html]] | homepage-backup | failed |
UploadPlugin uses the following sequence for finding parameters :
#''macro'' parameters
#''Options'' saved in cookies
#''Plugin'' default values
!Options used by UploadPlugin
| Option | Value | Default |
|Upload Username: |<<option txtUploadUserName>>| |
|Upload Password: |<<option pasUploadPassword>>| |
|Url of the UploadService script: |<<option txtUploadStoreUrl urlInput>>| store.php |
|Relative Directory where to store the file: |<<option txtUploadDir urlInput>>| . (the script directory) |
|Filename of the uploaded file: |<<option txtUploadFilename urlInput>>| index.html |
|Directory to backup file on webserver^^(1)^^: |<<option txtUploadBackupDir urlInput>>| //null// (none/no backup) |
|Log in UploadLog |<<option chkUploadLog>> Trace Upload| true |
|Maximum of lines in UploadLog |<<option txtUploadLogMaxLine>>| 10 |
^^(1)^^No backup if Backup Directory is empty, the previous file will be overwritten. Use a '.' to backup in the script directory.
<<upload>> with these options.
!Upload Macro parameters
{{{
<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
Optional positional parameters can be passed to overwrite UploadOptions.
}}}
!UploadToFile Macro Macro parameters
{{{
<<uploadTofile [filename [tiddlerTitle]]>>
tiddlerTitle, filename: if omitted the title of the current tiddler
}}}
<<uploadToFile allowedsites.txt allowedsites.txt>>
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.0|
|''Date:''|May 5, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (#3125)|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 0,
date: new Date("May 5, 2007"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0 (#3125)'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
var storeUrl