/***
|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;
}
//}}}
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Version|3.5.5|
|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|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
When 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.)
This 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.
!!!!!Usage
<<<
{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}
invokes the built-in importTiddlers macro (TW2.1.x+). If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)
{{{<<importTiddlers link label tooltip>>}}}
The ''link'' keyword creates an "import tiddlers" link that when clicked to show/hide import control panel. ''label'' and ''tooltip'' are optional text parameters (enclosed in quotes or {{{[[...]]}}}, and allow you to override the default display text for the link and the mouseover help text, respectively.
{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content
<<importTiddlers inline>>
Press ''[browse]'' to select a TiddlyWiki document file to import, and then press ''[open]''. Alternatively, you can type in the path/filename or a remote document URL (starting with http://). When you have entered the desired source location, press ''[load]'' to retrieve the tiddlers from the remote source. //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.//
Select 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.
''select: all, new, changes, or differences''
You 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:
>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document
>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)
''Import Tagging:''
Tiddlers 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.
''Skip, Rename, Merge, or Replace:''
When 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]''.
To 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.
//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.//
''Import Report History''
When 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.
When 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.
If 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.
Note: 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.
<<<
!!!!!Installation
<<<
copy/paste the following tiddlers into your document:
''ImportTiddlersPlugin''
''ImportTiddlersPluginPatch2.1.x'' (only for installation in TW2.1.x or earlier)
(both tagged with <<tag systemConfig>>)
>Important Notes:
>* As of 6/27/2007, "patch" functions that provide backward-compatibility with TW2.1.x and earlier have been split into a separate [[ImportTiddlersPluginPatch2.1.x]] tiddler to reduce installation overhead for //this// plugin. You only need to install this additional plugin tiddler when using ImportTiddlersPlugin in documents using TW2.1.x or earlier.
>* As of 3/21/2007, the interactive {{{<<importTiddlers>>}}} and non-interactive {{{<<loadTiddlers>>}}} macro definitions and related code have been split into separate [[ImportTiddlersPlugin]] and [[LoadTiddlersPlugin]] to permit selective installation of either the interactive and/or non-interactive macro functions
''Quick Installation Tip #1:''
If 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.
<<<
!!!!!Revision History
<<<
''2007.06.27 [3.5.5]'' added missing 'fields' params to saveTiddler() calls. Fixes problem where importing tiddlers would lose the custom fields. Also, moved functions for backward-compatibility with TW2.1.x to separate [[ImportTiddlersPluginPatch2.1.x]] tiddler, reducing the size of //this// plugin tiddler by a significant amount.
''2007.06.25 [3.5.4]'' added calls to store.suspendNotifications() and store.resumeNotifications(). Eliminates redisplay processing overhead DURING import activities
|please see [[ImportTiddlersPluginHistory]] for additional revision details|
''2005.07.20 [1.0.0]'' Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
// // ''MACRO DEFINITION''
//{{{
// Version
version.extensions.importTiddlers = {major: 3, minor: 5, revision: 5, date: new Date(2007,6,27)};
// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;
// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;
merge(config.macros.importTiddlers,{
label: "import tiddlers",
prompt: "Copy tiddlers from another document",
openMsg: "Opening %0",
openErrMsg: "Could not open %0 - error=%1",
readMsg: "Read %0 bytes from %1",
foundMsg: "Found %0 tiddlers in %1",
countMsg: "%0 tiddlers selected for import",
importedMsg: "Imported %0 of %1 tiddlers from %2",
loadText: "please load a document...",
closeText: "close", // text for close button when remote file is loaded
doneText: "done", // text for close button when remote file is not loaded
src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)
proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)
useProxy: false, // use specific proxy script in front of remote URL
inbound: null, // hash-indexed array of tiddlers from other document
newTags: "", // text of tags added to imported tiddlers
addTags: true, // add new tags to imported tiddlers
listsize: 8, // # of lines to show in imported tiddler list
importTags: true, // include tags from remote source document when importing a tiddler
keepTags: true, // retain existing tags when replacing a tiddler
index: 0, // current processing index in import list
sort: "" // sort order for imported tiddler listbox
});
if (config.macros.importTiddlers.coreHandler==undefined)
config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
if (config.macros.importTiddlers.coreHandler)
config.macros.importTiddlers.coreHandler.apply(this,arguments);
else
createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
}
else if (params[0]=='link') { // show link to floating panel
var label=params[1]?params[1]:this.label;
var prompt=params[2]?params[2]:this.prompt;
createTiddlyButton(place,label,prompt,onClickImportMenu);
}
else if (params[0]=='inline') {// show panel as INLINE tiddler content
createImportPanel(place);
document.getElementById("importPanel").style.position="static";
document.getElementById("importPanel").style.display="block";
}
else if (config.macros.loadTiddlers)
config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
if (!e) var e = window.event;
var parent=resolveTarget(e).parentNode;
var panel = document.getElementById("importPanel");
if (panel==undefined || panel.parentNode!=parent)
panel=createImportPanel(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" ;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
// // Create control panel: HTML, CSS
//{{{
function createImportPanel(place) {
var panel=document.getElementById("importPanel");
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(config.macros.importTiddlers.css,"importTiddlers");
panel=createTiddlyElement(place,"span","importPanel",null,null)
panel.innerHTML=config.macros.importTiddlers.html;
refreshImportList();
var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
document.getElementById("importSourceURL").value=siteURL;
config.macros.importTiddlers.src=siteURL;
var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
document.getElementById("importSiteProxy").value=siteProxy;
config.macros.importTiddlers.proxy=siteProxy;
return panel;
}
//}}}
// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
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;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\
#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:24%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\
';
//}}}
// // HTML
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
import from\
<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
onClick="document.getElementById(\'importLocalPanel\').style.display=this.checked?\'block\':\'none\';\
document.getElementById(\'importHTTPPanel\').style.display=!this.checked?\'block\':\'none\'"> local file\
<input type="radio" class="rad" name="importFrom" id="importFromWeb" value="http"\
onClick="document.getElementById(\'importLocalPanel\').style.display=!this.checked?\'block\':\'none\';\
document.getElementById(\'importHTTPPanel\').style.display=this.checked?\'block\':\'none\'"> web server\
</td><td align=right>\
<input type=checkbox class="chk" id="chkImportReport" checked\
onClick="config.options[\'chkImportReport\']=this.checked;"> create a report\
</td></tr></table>\
<!-- import from local file -->\
<div id="importLocalPanel" style="display:block;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\
local document path/filename:<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
onKeyUp="config.macros.importTiddlers.src=this.value"\
onChange="config.macros.importTiddlers.src=this.value;">\
</div><!--panel-->\
\
<!-- import from http server -->\
<div id="importHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\
<table><tr><td align=left>\
remote document URL:<br>\
</td><td align=right>\
<input type="checkbox" class="chk" id="importUseProxy"\
onClick="config.macros.importTiddlers.useProxy=this.checked;\
document.getElementById(\'importSiteProxy\').style.display=this.checked?\'block\':\'none\'"> use a proxy script\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
onKeyUp="config.macros.importTiddlers.proxy=this.value"\
onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
onKeyUp="config.macros.importTiddlers.src=this.value"\
onChange="config.macros.importTiddlers.src=this.value;">\
</div><!--panel-->\
\
<table><tr><td align=left>\
select:\
<a href="JavaScript:;" id="importSelectAll"\
onclick="onClickImportButton(this)" title="select all tiddlers">\
all </a>\
<a href="JavaScript:;" id="importSelectNew"\
onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\
added </a> \
<a href="JavaScript:;" id="importSelectChanges"\
onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\
changes </a> \
<a href="JavaScript:;" id="importSelectDifferences"\
onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\
differences </a> \
<a href="JavaScript:;" id="importToggleFilter"\
onclick="onClickImportButton(this)" title="show/hide selection filter">\
filter </a> \
</td><td align=right>\
<a href="JavaScript:;" id="importListSmaller"\
onclick="onClickImportButton(this)" title="reduce list size">\
– </a>\
<a href="JavaScript:;" id="importListLarger"\
onclick="onClickImportButton(this)" title="increase list size">\
+ </a>\
<a href="JavaScript:;" id="importListMaximize"\
onclick="onClickImportButton(this)" title="maximize/restore list size">\
= </a>\
</td></tr></table>\
<select id="importList" size=8 multiple\
onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<input type=checkbox class="chk" id="chkAddTags" checked\
onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \
<input type=checkbox class="chk" id="chkImportTags" checked\
onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \
<input type=checkbox class="chk" id="chkKeepTags" checked\
onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\
<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\
<div align=center>\
<input type=button id="importLoad" class="importButton" style="width:32%" value="load"\
title="load listbox with tiddlers from source document"\
onclick="onClickImportButton(this)">\
<input type=button id="importStart" class="importButton" style="width:32%" value="import"\
title="add selected source tiddlers to the current document"\
onclick="onClickImportButton(this)">\
<input type=button id="importClose" class="importButton" style="width:32%" value="close"\
title="clear listbox or hide control panel"\
onclick="onClickImportButton(this)">\
</div>\
<div id="importCollisionPanel">\
tiddler already exists:\
<input type=text id="importNewTitle" size=15 autocomplete=off">\
<div align=center>\
<input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\
title="do not import this tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importRename" class="importButton" style="width:23%" value="rename"\
title="rename the incoming tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\
title="append the incoming tiddler to the existing tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\
title="discard the existing tiddler"\
onclick="onClickImportButton(this)">\
</div>\
</div>\
';
//}}}
// // Control interactions
//{{{
function onClickImportButton(which)
{
// DEBUG alert(which.id);
var theList = document.getElementById('importList');
if (!theList) return;
var thePanel = document.getElementById('importPanel');
var theCollisionPanel = document.getElementById('importCollisionPanel');
var theNewTitle = document.getElementById('importNewTitle');
var count=0;
switch (which.id)
{
case 'fileImportSource':
case 'importLoad': // load import source into hidden frame
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
if (config.macros.importTiddlers.src=="") break;
// Load document, read it's DOM and fill the list
config.macros.importTiddlers.loadRemoteFile(config.macros.importTiddlers.src,
function(success,params,txt,src,xhr) {
if (!success) { displayMessage(config.macros.importTiddlers.openErrMsg.format([src,xhr.status])); return; }
var tiddlers = config.macros.importTiddlers.readTiddlersFromHTML(txt);
var count=tiddlers?tiddlers.length:0;
var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
displayMessage(config.macros.importTiddlers.foundMsg.format([count,src]));
config.macros.importTiddlers.inbound=tiddlers;
window.refreshImportList(0);
});
break;
case 'importSelectAll': // select all tiddler list items (i.e., not headings)
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
if (theList.options[t].value=="") continue;
theList.options[t].selected=true;
count++;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectNew': // select tiddlers not in current document
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importToggleFilter': // show/hide filter
case 'importFilter': // apply filter
alert("coming soon!");
break;
case 'importStart': // initiate the import processing
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.index=0;
config.macros.importTiddlers.index=importTiddlers(0);
importStopped();
break;
case 'importClose': // unload imported tiddlers or hide the import control panel
// if imported tiddlers not loaded, close the import control panel
if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
break;
case 'importSkip': // don't import the tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status='skipped after asking'; // mark item as skipped
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item
importStopped();
break;
case 'importRename': // change name of imported tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status = 'renamed from '+theImported.title; // mark item as renamed
theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title
theItem.value = theNewTitle.value; // change the listbox item text
theItem.text = theNewTitle.value; // change the listbox item text
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importMerge': // join existing and imported tiddler content
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
var theText = theExisting.text+'\n----\n^^merged from: ';
theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\n';
theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
var theDate = new Date();
var theTags = theExisting.getTags()+' '+theImported.getTags();
theImported.set(null,theText,null,theDate,theTags);
theImported.status = 'merged with '+theExisting.title; // mark item as merged
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item
importStopped();
break;
case 'importReplace': // substitute imported tiddler for existing tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
theImported.status = 'replaces '+theExisting.title; // mark item for replace
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importListSmaller': // decrease current listbox size, minimum=5
if (theList.options.length==1) break;
theList.size-=(theList.size>5)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListLarger': // increase current listbox size, maximum=number of items in list
if (theList.options.length==1) break;
theList.size+=(theList.size<theList.options.length)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListMaximize': // toggle listbox size between current and maximum
if (theList.options.length==1) break;
theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;
break;
}
}
//}}}
// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
var theList = document.getElementById("importList");
if (!theList) return;
// if nothing to show, reset list content and size
if (!config.macros.importTiddlers.inbound)
{
while (theList.length > 0) { theList.options[0] = null; }
theList.options[0]=new Option(config.macros.importTiddlers.loadText,"",false,false);
theList.size=config.macros.importTiddlers.listsize;
document.getElementById('importLoad').disabled=false;
document.getElementById('fileImportSource').disabled=false;
document.getElementById('importFromFile').disabled=false;
document.getElementById('importFromWeb').disabled=false;
document.getElementById('importClose').value=config.macros.importTiddlers.closeText;
return;
}
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading
if (selectedIndex==1) config.macros.importTiddlers.sort='title';
if (selectedIndex==2) config.macros.importTiddlers.sort='modified';
if (selectedIndex==3) config.macros.importTiddlers.sort='tags';
if (selectedIndex>3) {
// display selected tiddler count
for (var t=0,count=0; t < theList.options.length; t++) {
if (!theList.options[t].selected) continue;
if (theList.options[t].value!="")
count+=1;
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++;
}
}
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
return; // no refresh needed
}
// there are inbound tiddlers loaded... disable inapplicable controls...
document.getElementById('importLoad').disabled=true;
document.getElementById('fileImportSource').disabled=true;
document.getElementById('importFromFile').disabled=true;
document.getElementById('importFromWeb').disabled=true;
document.getElementById('importClose').value=config.macros.importTiddlers.doneText;
// get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)
var tiddlers=config.macros.importTiddlers.inbound;
tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
// 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+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);
// output the tiddler list
switch(config.macros.importTiddlers.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 "modified":
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
var lastSection = "";
for(var t = 0; t < tiddlers.length; t++) {
var tiddler = tiddlers[t];
var theSection = tiddler.modified.toLocaleDateString();
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
if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;
if (theList.size>theList.options.length) theList.size=theList.options.length;
}
//}}}
// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
if (!config.macros.importTiddlers.inbound) return -1;
var theList = document.getElementById('importList');
if (!theList) return;
var t;
// if starting new import, reset import status flags
if (startIndex==0)
for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)
config.macros.importTiddlers.inbound[t].status="";
for (var i=startIndex; i<theList.options.length; i++)
{
// if list item is not selected or is a heading (i.e., has no value), skip it
if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))
continue;
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==t) break;
var inbound = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(inbound.title);
// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
if (inbound.status=="added")
continue;
// don't import the "ImportedTiddlers" history from the other document...
if (inbound.title=='ImportedTiddlers')
continue;
// if tiddler exists and import not marked for replace or merge, stop importing
if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
return i;
// assemble tags (remote + existing + added)
var newTags = "";
if (config.macros.importTiddlers.importTags)
newTags+=inbound.getTags() // import remote tags
if (config.macros.importTiddlers.keepTags && theExisting)
newTags+=" "+theExisting.getTags(); // keep existing tags
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newTags+=" "+config.macros.importTiddlers.newTags; // add new tags
inbound.set(null,null,null,null,newTags.trim());
// set the status to 'added' (if not already set by the 'ask the user' UI)
inbound.status=(inbound.status=="")?'added':inbound.status;
// do the import!
store.suspendNotifications();
store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
store.resumeNotifications();
}
return(-1); // signals that we really finished the entire list
}
//}}}
//{{{
function importStopped()
{
var theList = document.getElementById('importList');
var theNewTitle = document.getElementById('importNewTitle');
if (!theList) return;
if (config.macros.importTiddlers.index==-1)
importReport(); // import finished... generate the report
else
{
// import collision... show the collision panel and set the title edit field
document.getElementById('importCollisionPanel').style.display='block';
theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;
}
}
//}}}
// // ''REPORT GENERATOR''
//{{{
function importReport(quiet)
{
if (!config.macros.importTiddlers.inbound) return;
// DEBUG alert('importReport: start');
// if import was not completed, the collision panel will still be open... close it now.
var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';
// get the alphasorted list of tiddlers
var tiddlers = config.macros.importTiddlers.inbound;
// gather the statistics
var count=0;
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].status && tiddlers[t].status.trim().length && tiddlers[t].status.substr(0,7)!="skipped") count++;
// generate a report
if (count && config.options.chkImportReport) {
// get/create the report tiddler
var theReport = store.getTiddler('ImportedTiddlers');
if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }
// format the report content
var now = new Date();
var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\n";
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newText += "imported tiddlers were tagged with: \""+config.macros.importTiddlers.newTags+"\"\n";
newText += "<<<\n";
for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
newText += "<<<\n";
// update the ImportedTiddlers content and show the tiddler
theReport.text = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
theReport.modifier = config.options.txtUserName;
theReport.modified = new Date();
store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }
}
// reset status flags
for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";
// mark document as dirty and let display update as needed
if (count) { store.setDirty(true); store.notifyAll(); }
// always show final message when tiddlers were actually loaded
if (count) displayMessage(config.macros.importTiddlers.importedMsg.format([count,tiddlers.length,config.macros.importTiddlers.src]));
}
//}}}
// // File and XMLHttpRequest I/O
//{{{
config.macros.importTiddlers.fileExists=function(theFile) {
var found=false;
// DEBUG: alert('testing fileExists('+theFile+')...');
if(window.Components) {
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
catch(e) { return false; } // security access denied
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
try { file.initWithPath(theFile); }
catch(e) { return false; } // invalid directory
found = file.exists();
}
else { // use ActiveX FSO object for MSIE
var fso = new ActiveXObject("Scripting.FileSystemObject");
found = fso.FileExists(theFile)
}
// DEBUG: alert(theFile+" "+(found?"exists":"not found"));
return found;
}
config.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet) {
if (src==undefined || !src.length) return null; // filename is required
if (!quiet) clearMessage();
if (!quiet) displayMessage(this.openMsg.format([src]));
if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if src is relative (i.e., not a URL)
if (!this.fileExists(src)) { // if file cannot be found, might be relative path.. try fixup
var pathPrefix=document.location.href; // get current document path and trim off filename
var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\");
if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
src=pathPrefix+src;
if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
}
}
if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
var txt=loadFile(src);
if ((txt==null)||(txt==false)) // file didn't load
{ if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(filesystem error)"])); }
else {
if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src]));
if (callback) callback(true,quiet,convertUTF8ToUnicode(txt),src,null);
}
}
else {
var xhr=loadRemoteFile(src,callback,quiet);
if (!quiet && !xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
}
}
config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
var remoteStore=new TiddlyWiki();
remoteStore.importTiddlyWiki(html);
return remoteStore.getTiddlers("title");
}
//}}}