Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
<<forEachTiddler
where
'!tiddler.tags.contains("systemConfig") && ! tiddler.tags.contains("hidden") && ! tiddler.tags.contains("infobox") && ! tiddler.title.contains("Spec") && ! tiddler.title.contains("Example") && ! tiddler.title.contains("Test") && ! tiddler.title.contains("Plugin") && ! tiddler.title.contains("Default") && ! tiddler.title.contains("Site") && ! tiddler.title.contains("Simile") && ! tiddler.title.contains("Style") && ! tiddler.title.contains("MainMenu")&& ! tiddler.title.contains("Clock")'
sortBy
'tiddler.title.toUpperCase()'
script
'
function getGroupCaption(tiddler) {
return tiddler.title.substr(0,1).toUpperCase();
}
function getGroupTitle(tiddler, context) {
if (!context.lastGroup || context.lastGroup != getGroupCaption(tiddler)) {
context.lastGroup = getGroupCaption(tiddler);
return "* {{{"+(context.lastGroup?context.lastGroup:"no tags")+"}}}\n";
} else
return "";
}
'
write
'getGroupTitle(tiddler, context)+"** [[" + tiddler.title+"]]\n"'
>>
/***
|Name|CalendarPlugin|
|Source|http://www.TiddlyTools.com/#CalendarPlugin|
|Version|1.5.0|
|Author|Eric Shulman|
|Original Author|SteveRumsby|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|display monthly and yearly calendars|
NOTE: For //enhanced// date popup display, optionally install [[DatePlugin]] and [[ReminderMacros]]
!!!Usage:
<<<
|{{{<<calendar>>}}}|full-year calendar for the current year|
|{{{<<calendar year>>}}}|full-year calendar for the specified year|
|{{{<<calendar year month>>}}}|one month calendar for the specified month and year|
|{{{<<calendar thismonth>>}}}|one month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|one month calendar for last month|
|{{{<<calendar nextmonth>>}}}|one month calendar for next month|
|{{{<<calendar +n>>}}}<br>{{{<<calendar -n>>}}}|one month calendar for a month +/- 'n' months from now|
<<<
!!!Configuration:
<<<
|''First day of week:''<br>{{{config.options.txtCalFirstDay}}}|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''<br>{{{config.options.txtCalStartOfWeekend}}}|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|
<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
|''Week number display format:''<br>{{{config.options.txtWeekNumberDisplayFormat }}}|<<option txtWeekNumberDisplayFormat >>|
|''Week number link format:''<br>{{{config.options.txtWeekNumberLinkFormat }}}|<<option txtWeekNumberLinkFormat >>|
<<<
!!!Revisions
<<<
2009.04.31 [1.5.0] rewrote onClickCalendarDate() (popup handler) and added config.options.txtCalendarReminderTags. Partial code reduction/cleanup. Assigned true version number (1.5.0)
2008.09.10 added '+n' (and '-n') param to permit display of relative months (e.g., '+6' means 'six months from now', '-3' means 'three months ago'. Based on suggestion from Jean.
2008.06.17 added support for config.macros.calendar.todaybg
2008.02.27 in handler(), DON'T set hard-coded default date format, so that *customized* value (pre-defined in config.macros.calendar.journalDateFmt is used.
2008.02.17 in createCalendarYear(), fix next/previous year calculation (use parseInt() to convert to numeric value). Also, use journalDateFmt for date linking when NOT using [[DatePlugin]].
2008.02.16 in createCalendarDay(), week numbers now created as TiddlyLinks, allowing quick creation/navigation to 'weekly' journals (based on request from Kashgarinn)
2008.01.08 in createCalendarMonthHeader(), 'month year' heading is now created as TiddlyLink, allowing quick creation/navigation to 'month-at-a-time' journals
2007.11.30 added 'return false' to onclick handlers (prevent IE from opening blank pages)
2006.08.23 added handling for weeknumbers (code supplied by Martin Budden (see 'wn**' comment marks). Also, incorporated updated by Jeremy Sheeley to add caching for reminders (see [[ReminderMacros]], if installed)
2005.10.30 in config.macros.calendar.handler(), use 'tbody' element for IE compatibility. Also, fix year calculation for IE's getYear() function (which returns '2005' instead of '105'). Also, in createCalendarDays(), use showDate() function (see [[DatePlugin]], if installed) to render autostyled date with linked popup. Updated calendar stylesheet definition: use .calendar class-specific selectors, add text centering and margin settings
2006.05.29 added journalDateFmt handling
<<<
!!!Code
***/
//{{{
version.extensions.CalendarPlugin= { major: 1, minor: 5, revision: 0, date: new Date(2009,5,31)};
//}}}
//{{{
if(config.options.txtCalFirstDay == undefined)
config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
config.options.txtCalStartOfWeekend = 5;
if(config.options.chkDisplayWeekNumbers == undefined)
config.options.chkDisplayWeekNumbers = false;
if(config.options.chkDisplayWeekNumbers)
config.options.txtCalFirstDay = 0;
if(config.options.txtWeekNumberDisplayFormat == undefined)
config.options.txtWeekNumberDisplayFormat = 'w0WW';
if(config.options.txtWeekNumberLinkFormat == undefined)
config.options.txtWeekNumberLinkFormat = 'YYYY-w0WW';
if(config.options.txtCalendarReminderTags == undefined)
config.options.txtCalendarReminderTags = 'reminder';
config.macros.calendar = {
monthnames:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
daynames:['M','T','W','T','F','S','S'],
todaybg:'#ccccff',
weekendbg:'#c0c0c0',
monthbg:'#e0e0e0',
holidaybg:'#ffc0c0',
journalDateFmt:'DD MMM YYYY',
monthdays:[31,28,31,30,31,30,31,31,30,31,30,31],
holidays:[ ] // for customization see [[CalendarPluginConfig]]
};
//}}}
//{{{
function calendarIsHoliday(date)
{
var longHoliday = date.formatString('0DD/0MM/YYYY');
var shortHoliday = date.formatString('0DD/0MM');
for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
if( config.macros.calendar.holidays[i]==longHoliday
|| config.macros.calendar.holidays[i]==shortHoliday)
return true;
}
return false;
}
//}}}
//{{{
config.macros.calendar.handler = function(place,macroName,params) {
var calendar = createTiddlyElement(place, 'table', null, 'calendar', null);
var tbody = createTiddlyElement(calendar, 'tbody');
var today = new Date();
var year = today.getYear();
if (year<1900) year+=1900;
// get journal format from SideBarOptions (ELS 5/29/06 - suggested by MartinBudden)
var text = store.getTiddlerText('SideBarOptions');
var re = new RegExp('<<(?:newJournal)([^>]*)>>','mg'); var fm = re.exec(text);
if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }
var month=-1;
if (params[0] == 'thismonth') {
var month=today.getMonth();
} else if (params[0] == 'lastmonth') {
var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
} else if (params[0] == 'nextmonth') {
var month = today.getMonth()+1; if (month>11) { month=0; year++; }
} else if (params[0]&&'+-'.indexOf(params[0].substr(0,1))!=-1) {
var month = today.getMonth()+parseInt(params[0]);
if (month>11) { year+=Math.floor(month/12); month%=12; };
if (month<0) { year+=Math.floor(month/12); month=12+month%12; }
} else if (params[0]) {
year = params[0];
if(params[1]) month=parseInt(params[1])-1;
if (month>11) month=11; if (month<0) month=0;
}
if (month!=-1) {
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
} else {
cacheReminders(new Date(year, 0, 1, 0, 0), 366);
createCalendarYear(tbody, year);
}
window.reminderCacheForCalendar = null;
}
//}}}
//{{{
// cache used to store reminders while the calendar is being rendered
// it will be renulled after the calendar is fully rendered.
window.reminderCacheForCalendar = null;
//}}}
//{{{
function cacheReminders(date, leadtime)
{
if (window.findTiddlersWithReminders == null) return;
window.reminderCacheForCalendar = {};
var leadtimeHash = [];
leadtimeHash [0] = 0;
leadtimeHash [1] = leadtime;
var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
for(var i = 0; i < t.length; i++) {
//just tag it in the cache, so that when we're drawing days, we can bold this one.
window.reminderCacheForCalendar[t[i]['matchedDate']] = 'reminder:' + t[i]['params']['title'];
}
}
//}}}
//{{{
function createCalendarOneMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, 'tr');
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon]+' '+year, true, year, mon);
row = createTiddlyElement(calendar, 'tr');
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, 'tr');
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon]+' '+ year, false, year, mon);
row = createTiddlyElement(calendar, 'tr');
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarYear(calendar, year)
{
var row;
row = createTiddlyElement(calendar, 'tr');
var back = createTiddlyElement(row, 'td');
var backHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, parseInt(year)-1);
return false; // consume click
};
createTiddlyButton(back, '<', 'Previous year', backHandler);
back.align = 'center';
var yearHeader = createTiddlyElement(row, 'td', null, 'calendarYear', year);
yearHeader.align = 'center';
yearHeader.setAttribute('colSpan',config.options.chkDisplayWeekNumbers?22:19);//wn**
var fwd = createTiddlyElement(row, 'td');
var fwdHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, parseInt(year)+1);
return false; // consume click
};
createTiddlyButton(fwd, '>', 'Next year', fwdHandler);
fwd.align = 'center';
createCalendarMonthRow(calendar, year, 0);
createCalendarMonthRow(calendar, year, 3);
createCalendarMonthRow(calendar, year, 6);
createCalendarMonthRow(calendar, year, 9);
}
//}}}
//{{{
function createCalendarMonthRow(cal, year, mon)
{
var row = createTiddlyElement(cal, 'tr');
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
row = createTiddlyElement(cal, 'tr');
createCalendarDayHeader(row, 3);
createCalendarDayRows(cal, year, mon);
}
//}}}
//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
var month;
if (nav) {
var back = createTiddlyElement(row, 'td');
back.align = 'center';
back.style.background = config.macros.calendar.monthbg;
var backMonHandler = function() {
var newyear = year;
var newmon = mon-1;
if(newmon == -1) { newmon = 11; newyear = newyear-1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
};
createTiddlyButton(back, '<', 'Previous month', backMonHandler);
month = createTiddlyElement(row, 'td', null, 'calendarMonthname')
createTiddlyLink(month,name,true);
month.setAttribute('colSpan', config.options.chkDisplayWeekNumbers?6:5);//wn**
var fwd = createTiddlyElement(row, 'td');
fwd.align = 'center';
fwd.style.background = config.macros.calendar.monthbg;
var fwdMonHandler = function() {
var newyear = year;
var newmon = mon+1;
if(newmon == 12) { newmon = 0; newyear = newyear+1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
};
createTiddlyButton(fwd, '>', 'Next month', fwdMonHandler);
} else {
month = createTiddlyElement(row, 'td', null, 'calendarMonthname', name)
month.setAttribute('colSpan',config.options.chkDisplayWeekNumbers?8:7);//wn**
}
month.align = 'center';
month.style.background = config.macros.calendar.monthbg;
}
//}}}
//{{{
function createCalendarDayHeader(row, num)
{
var cell;
for(var i = 0; i < num; i++) {
if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, 'td');//wn**
for(var j = 0; j < 7; j++) {
var d = j + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
cell = createTiddlyElement(row, 'td', null, null, config.macros.calendar.daynames[d]);
if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
cell.style.background = config.macros.calendar.weekendbg;
}
}
}
//}}}
//{{{
function createCalendarDays(row, col, first, max, year, mon) {
var i;
if (config.options.chkDisplayWeekNumbers){
if (first<=max) {
var ww = new Date(year,mon,first);
var td=createTiddlyElement(row, 'td');//wn**
var link=createTiddlyLink(td,ww.formatString(config.options.txtWeekNumberLinkFormat),false);
link.appendChild(document.createTextNode(
ww.formatString(config.options.txtWeekNumberDisplayFormat)));
}
else createTiddlyElement(row, 'td');//wn**
}
for(i = 0; i < col; i++)
createTiddlyElement(row, 'td');
var day = first;
for(i = col; i < 7; i++) {
var d = i + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
var daycell = createTiddlyElement(row, 'td');
var isaWeekend=((d==(config.options.txtCalStartOfWeekend-0)
|| d==(config.options.txtCalStartOfWeekend-0+1))?true:false);
if(day > 0 && day <= max) {
var celldate = new Date(year, mon, day);
// ELS 10/30/05 - use <<date>> macro's showDate() function to create popup
// ELS 05/29/06 - use journalDateFmt
if (window.showDate) showDate(daycell,celldate,'popup','DD',
config.macros.calendar.journalDateFmt,true, isaWeekend);
else {
if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
var title = celldate.formatString(config.macros.calendar.journalDateFmt);
if(calendarIsHoliday(celldate))
daycell.style.background = config.macros.calendar.holidaybg;
var now=new Date();
if ((now-celldate>=0) && (now-celldate<86400000)) // is today?
daycell.style.background = config.macros.calendar.todaybg;
if(window.findTiddlersWithReminders == null) {
var link = createTiddlyLink(daycell, title, false);
link.appendChild(document.createTextNode(day));
} else
var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
}
}
day++;
}
}
//}}}
//{{{
// Create a pop-up containing:
// * a link to a tiddler for this date
// * a 'new tiddler' link to add a reminder for this date
// * links to current reminders for this date
// NOTE: this code is only used if [[ReminderMacros]] is installed AND [[DatePlugin]] is //not// installed.
function onClickCalendarDate(ev) { ev=ev||window.event;
var d=new Date(this.getAttribute('title')); var date=d.formatString(config.macros.calendar.journalDateFmt);
var p=Popup.create(this); if (!p) return;
createTiddlyLink(createTiddlyElement(p,'li'),date,true);
var rem='\\n\\<\\<reminder day:%0 month:%1 year:%2 title: \\>\\>';
rem=rem.format([d.getDate(),d.getMonth()+1,d.getYear()+1900]);
var cmd="<<newTiddler label:[[new reminder...]] prompt:[[add a new reminder to '%0']]"
+" title:[[%0]] text:{{store.getTiddlerText('%0','')+'%1'}} tag:%2>>";
wikify(cmd.format([date,rem,config.options.txtCalendarReminderTags]),p);
createTiddlyElement(p,'hr');
var t=findTiddlersWithReminders(d,[0,31],null,1);
for(var i=0; i<t.length; i++) {
var link=createTiddlyLink(createTiddlyElement(p,'li'), t[i].tiddler, false);
link.appendChild(document.createTextNode(t[i]['params']['title']));
}
Popup.show(); ev.cancelBubble=true; if (ev.stopPropagation) ev.stopPropagation(); return false;
}
//}}}
//{{{
function calendarMaxDays(year, mon)
{
var max = config.macros.calendar.monthdays[mon];
if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) max++;
return max;
}
//}}}
//{{{
function createCalendarDayRows(cal, year, mon)
{
var row = createTiddlyElement(cal, 'tr');
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1 + 7;
var day1 = -first1 + 1;
var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first2 < 0) first2 = first2 + 7;
var day2 = -first2 + 1;
var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first3 < 0) first3 = first3 + 7;
var day3 = -first3 + 1;
var max1 = calendarMaxDays(year, mon);
var max2 = calendarMaxDays(year, mon+1);
var max3 = calendarMaxDays(year, mon+2);
while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
row = createTiddlyElement(cal, 'tr');
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
}
}
//}}}
//{{{
function createCalendarDayRowsSingle(cal, year, mon)
{
var row = createTiddlyElement(cal, 'tr');
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1+ 7;
var day1 = -first1 + 1;
var max1 = calendarMaxDays(year, mon);
while(day1 <= max1) {
row = createTiddlyElement(cal, 'tr');
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
}
}
//}}}
//{{{
setStylesheet('.calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }', 'calendarStyles');
//}}}
// // override cookie settings for CalendarPlugin:
//{{{
config.options.txtCalFirstDay=6;
config.options.txtCalStartOfWeekend=5;
//}}}
// // override internal default settings for CalendarPlugin:
//{{{
config.macros.calendar.journalDateFmt="DDD MMM 0DD YYYY";
//}}}
<<SimileTimeline ClockTimelineSpec>>
|timelineHeight:|200|
|band0.width:|15%|
|band0.intervalUnit:|SECOND|
|band0.intervalPixels:|40|
|band0.eventSourceType:|timer|
|band0.eventSourceParams:|1|
|band1.width:|15%|
|band1.intervalUnit:|MINUTE|
|band1.intervalPixels:|40|
|band1.highlight:|false|
|band2.width:|15%|
|band2.intervalUnit:|HOUR|
|band2.intervalPixels:|60|
|band2.highlight:|false|
|band3.width:|15%|
|band3.intervalUnit:|WEEK|
|band3.intervalPixels:|100|
|band3.highlight:|false|
|band4.width:|15%|
|band4.intervalUnit:|MONTH|
|band4.intervalPixels:|100|
|band4.highlight:|false|
|band5.width:|15%|
|band5.intervalUnit:|YEAR|
|band5.intervalPixels:|200|
|band5.highlight:|false|
/***
|Name|CopyTiddlerPlugin|
|Source|http://www.TiddlyTools.com/#CopyTiddlerPlugin|
|Version|3.2.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.3|
|Type|plugin|
|Requires||
|Overrides||
|Description|Quickly create a copy of any existing tiddler|
!!!Usage
<<<
The plugin automatically updates the default (shadow) ToolbarCommands definitions to insert the ''copyTiddler'' command, which will appear as ''copy'' when a tiddler is rendered. If you are already using customized toolbar definitions, you will need to manually add the ''copyTiddler'' toolbar command to your existing ToolbarCommands tiddler, e.g.:
{{{
|EditToolbar|... copyTiddler ... |
}}}
When the ''copy'' command is selected, a new tiddler is created containing an exact copy of the current text/tags/fields, using a title of "{{{TiddlerName (n)}}}", where ''(n)'' is the next available number (starting with 1, of course). If you copy while //editing// a tiddler, the current values displayed in the editor are used (including any changes you may have already made to those values), and the new tiddler is immediately opened for editing.
The plugin also provides a macro that allows you to embed a ''copy'' command directly in specific tiddler content:
{{{
<<copyTiddler TidderName label:"..." prompt:"...">>
}}}
where
* ''TiddlerName'' (optional)<br>specifies the //source// tiddler to be copied. If omitted, the current containing tiddler (if any) will be copied.
* ''label:"..."'' (optional)<br>specifies text to use for the embedded link (default="copy TiddlerName")
* ''prompt:"..."'' (optional)<br>specifies mouseover 'tooltip' help text for link
//Note: to use non-default label/prompt values with the current containing tiddler, use "" for the TiddlerName//
<<<
!!!Configuration
<<<
<<option chkCopyTiddlerDate>> use date/time from existing tiddler (otherwise, use current date/time)
{{{<<option chkCopyTiddlerDate>>}}}
<<<
!!!Revisions
<<<
2009.06.08 [3.2.5] added option to use timestamp from source tiddler
2009.03.09 [3.2.4] fixed IE-specific syntax error
2009.03.02 [3.2.3] refactored code (again) to restore use of config.commands.copyTiddler.* custom settings
2009.02.13 [3.2.2] in click(), fix calls to displayTiddler() to use current tiddlerElem and use getTiddlerText() to permit copying of shadow tiddler content
2009.01.30 [3.2.1] fixed handling for copying field values when in edit mode
2009.01.23 [3.2.0] refactored code and added {{{<<copyTiddler TiddlerName>>}}} macro
2008.12.18 [3.1.4] corrected code for finding next (n) value when 'sparse' handling is in effect (thanks to RussThomas for identifying and diagnosing the problem)
2008.11.14 [3.1.3] added optional 'sparse' setting (avoids 'filling in' missing numbers that may have been previously deleted)
2008.11.14 [3.1.2] added optional 'zeroPad' setting
2008.11.14 [3.1.1] moved hard-coded '(n)' regex into 'suffixPattern' object property so it can be customized
2008.09.26 [3.1.0] changed new title generation to use '(n)' suffix instead of 'Copy of' prefix
2008.05.20 [3.0.3] in handler, when copying from VIEW mode, create duplicate array from existing tags array before saving new tiddler.
2007.12.19 [3.0.2] in handler, when copying from VIEW mode, duplicate custom fields before saving new tiddler. Thanks to bug report from Ken Girard.
2007.09.26 [3.0.1] in handler, use findContainingTiddler(src) to get tiddlerElem (and title). Allows 'copy' command to find correct tiddler when transcluded using {{{<<tiddler>>}}} macro or enhanced toolbar inclusion (see [[CoreTweaks]])
2007.06.28 [3.0.0] complete re-write to handle custom fields and alternative view/edit templates
2007.05.17 [2.1.2] use store.getTiddlerText() to retrieve tiddler content, so that SHADOW tiddlers can be copied correctly when in VIEW mode
2007.04.01 [2.1.1] in copyTiddler.handler(), fix check for editor fields by ensuring that found field actually has edit=='text' attribute
2007.02.05 [2.1.0] in copyTiddler.handler(), if editor fields (textfield and/or tagsfield) can't be found (i.e., tiddler is in VIEW mode, not EDIT mode), then get text/tags values from stored tiddler instead of active editor fields. Allows use of COPY toolbar directly from VIEW mode (based on a request from LaurentCharles)
2006.12.12 [2.0.0] completely rewritten so plugin just creates a new tiddler EDITOR with a copy of the current tiddler EDITOR contents, instead of creating the new tiddler in the STORE by copying the current tiddler values from the STORE.
2005.xx.xx [1.0.0] original version by Tim Morgan
<<<
!!!Code
***/
//{{{
version.extensions.CopyTiddlerPlugin= {major: 3, minor: 2, revision: 5, date: new Date(2009,6,8)};
// automatically tweak shadow EditTemplate to add 'copyTiddler' toolbar command (following 'cancelTiddler')
config.shadowTiddlers.ToolbarCommands=config.shadowTiddlers.ToolbarCommands.replace(/cancelTiddler/,'cancelTiddler copyTiddler');
if (config.options.chkCopyTiddlerDate===undefined) config.options.chkCopyTiddlerDate=false;
config.commands.copyTiddler = {
text: 'copy',
hideReadOnly: true,
tooltip: 'Make a copy of this tiddler',
notitle: 'this tiddler',
prefix: '',
suffixText: ' (%0)',
suffixPattern: / \(([0-9]+)\)$/,
zeroPad: 0,
sparse: false,
handler: function(event,src,title)
{ return config.commands.copyTiddler.click(src,event); },
click: function(here,ev) {
var tiddlerElem=story.findContainingTiddler(here);
var template=tiddlerElem?tiddlerElem.getAttribute('template'):null;
var title=here.getAttribute('from');
if (!title || !title.length) {
if (!tiddlerElem) return false;
else title=tiddlerElem.getAttribute('tiddler');
}
var root=title.replace(this.suffixPattern,''); // title without suffix
// find last matching title
var last=title;
if (this.sparse) { // don't fill-in holes... really find LAST matching title
var tids=store.getTiddlers('title','excludeLists');
for (var t=0; t<tids.length; t++) if (tids[t].title.startsWith(root)) last=tids[t].title;
}
// get next number (increment from last matching title)
var n=1; var match=this.suffixPattern.exec(last); if (match) n=parseInt(match[1])+1;
var newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]);
// if not sparse mode, find the next hole to fill in...
while (store.tiddlerExists(newTitle)||document.getElementById(story.idPrefix+newTitle))
{ n++; newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]); }
if (!story.isDirty(title)) { // if tiddler is not being EDITED
// duplicate stored tiddler (if any)
var text=store.getTiddlerText(title,'');
var who=config.options.txtUserName;
var when=new Date();
var newtags=[]; var newfields={};
var tid=store.getTiddler(title); if (tid) {
if (config.options.chkCopyTiddlerDate) var when=tid.modified;
for (var t=0; t<tid.tags.length; t++) newtags.push(tid.tags[t]);
store.forEachField(tid,function(t,f,v){newfields[f]=v;},true);
}
store.saveTiddler(newTitle,newTitle,text,who,when,newtags,newfields,true);
story.displayTiddler(tiddlerElem,newTitle,template);
} else {
story.displayTiddler(tiddlerElem,newTitle,template);
var fields=config.commands.copyTiddler.gatherFields(tiddlerElem); // get current editor fields
var newTiddlerElem=document.getElementById(story.idPrefix+newTitle);
for (var f=0; f<fields.length; f++) { // set fields in new editor
if (fields[f].name=='title') fields[f].value=newTitle; // rename title in new tiddler
var fieldElem=config.commands.copyTiddler.findField(newTiddlerElem,fields[f].name);
if (fieldElem) {
if (fieldElem.getAttribute('type')=='checkbox')
fieldElem.checked=fields[f].value;
else
fieldElem.value=fields[f].value;
}
}
}
story.focusTiddler(newTitle,'title');
return false;
},
findField: function(tiddlerElem,field) {
var inputs=tiddlerElem.getElementsByTagName('input');
for (var i=0; i<inputs.length; i++) {
if (inputs[i].getAttribute('type')=='checkbox' && inputs[i].field == field) return inputs[i];
if (inputs[i].getAttribute('type')=='text' && inputs[i].getAttribute('edit') == field) return inputs[i];
}
var tas=tiddlerElem.getElementsByTagName('textarea');
for (var i=0; i<tas.length; i++) if (tas[i].getAttribute('edit') == field) return tas[i];
var sels=tiddlerElem.getElementsByTagName('select');
for (var i=0; i<sels.length; i++) if (sels[i].getAttribute('edit') == field) return sels[i];
return null;
},
gatherFields: function(tiddlerElem) { // get field names and values from current tiddler editor
var fields=[];
// get checkboxes and edit fields
var inputs=tiddlerElem.getElementsByTagName('input');
for (var i=0; i<inputs.length; i++) {
if (inputs[i].getAttribute('type')=='checkbox')
if (inputs[i].field) fields.push({name:inputs[i].field,value:inputs[i].checked});
if (inputs[i].getAttribute('type')=='text')
if (inputs[i].getAttribute('edit')) fields.push({name:inputs[i].getAttribute('edit'),value:inputs[i].value});
}
// get textareas (multi-line edit fields)
var tas=tiddlerElem.getElementsByTagName('textarea');
for (var i=0; i<tas.length; i++)
if (tas[i].getAttribute('edit')) fields.push({name:tas[i].getAttribute('edit'),value:tas[i].value});
// get selection lists (droplist or listbox)
var sels=tiddlerElem.getElementsByTagName('select');
for (var i=0; i<sels.length; i++)
if (sels[i].getAttribute('edit')) fields.push({name:sels[i].getAttribute('edit'),value:sels[i].value});
return fields;
}
};
//}}}
// // MACRO DEFINITION
//{{{
config.macros.copyTiddler = {
label: 'copy',
prompt: 'Make a copy of %0',
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var title=params.shift();
params=paramString.parseParams('anon',null,true,false,false);
var label =getParam(params,'label',this.label+(title?' '+title:''));
var prompt =getParam(params,'prompt',this.prompt).format([title||this.notitle]);
var b=createTiddlyButton(place,label,prompt,
function(ev){return config.commands.copyTiddler.click(this,ev)});
b.setAttribute('from',title||'');
}
};
//}}}
All text and illustrations in this document <<date filedate "YYYY">> by <<message "config.options.txtUserName">>, unless otherwise noted.
Please note that this does NOT include the underlying wiki programming or any additional programming done by other programmers to extend the original functionality of this wiki.
/% Please note that this will grab the username of the most current editor in a shared setting as the copyright holder. If you want to change that, simply remove the macro after the word by and replace it with your preference. Also, the date will be updated to the current year by macro, so if you want to have a span of time, just add the starting year before macro code with appropriate indication of span (ie. a dash or the word "to") %/
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).
Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers.
''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.
''Access and Modify Tiddler Data''
You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields.
These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//
''Data Representation in a Tiddler''
The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]].
//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}
The data section is not displayed when viewing the tiddler (see also "The showData Macro").
Beside the data section a tiddler may have all kind of other content.
Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.
''Saving Changes''
The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.
''Notifications''
No notifications are sent when a tiddler's data value is changed through the "setData" methods.
''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.
''The showData Macro''
By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:
''Syntax:''
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
!Revision history
* v1.0.6 (2006-08-26)
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed:
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features:
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed:
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// DataTiddlerPlugin
//============================================================================
//============================================================================
// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {
version.extensions.DataTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006, 7, 26),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) {
TiddlyWiki.prototype.getTiddler = function(title) {
var t = this.tiddlers[title];
return (t !== undefined && t instanceof Tiddler) ? t : null;
};
}
//============================================================================
// DataTiddler Class
//============================================================================
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
function DataTiddler() {
}
DataTiddler = {
// Function to stringify a JavaScript value, producing the text for the data section content.
// (Must match the implementation of DataTiddler.parse.)
//
stringify : null,
// Function to parse the text for the data section content, producing a JavaScript value.
// (Must match the implementation of DataTiddler.stringify.)
//
parse : null
};
// Ensure access for IE
window.DataTiddler = DataTiddler;
// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------
// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};
// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler+ "("+t+")";
}
DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};
// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...)
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataObject(t);
};
// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.readDataSectionText(t);
};
// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------
// Internal.
//
// The original JSONError is not very user friendly,
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
if (ex.name == 'JSONError') {
ex.toString = function() {
return ex.name + ": "+ex.message+" ("+ex.text+")";
};
}
return ex;
};
// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
if (t.dataObject === undefined) {
var data = DataTiddler.readData(t);
t.dataObject = (data) ? data : {};
}
return t.dataObject;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
return (value === undefined) ? defaultValue : value;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
var oldValue = data[field];
if (value == defaultValue) {
if (oldValue !== undefined) {
delete data[field];
DataTiddler.save(tiddler);
}
return;
}
data[field] = value;
DataTiddler.save(tiddler);
};
// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
if (matches === null || !matches[2]) {
return null;
}
return matches[2];
};
// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
var text = DataTiddler.readDataSectionText(tiddler);
try {
return text ? DataTiddler.parse(text) : null;
} catch(ex) {
throw DataTiddler.extendJSONError(ex);
}
};
// Internal.
//
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
return DataTiddler.stringify(data);
};
// Internal.
//
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
var index = s.indexOf(subString, startIndex);
while ((index > 0) && (s[index-1] == '~')) {
index = s.indexOf(subString, index+1);
}
return index;
};
// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
// Special care must be taken to handle "<data>" and "</data>" texts inside
// a data section.
// Also take care not to use an escaped <data> (i.e. "~<data>") as the start
// of a data section. (Same for </data>)
// NOTE: we are explicitly searching for a data section that contains a JSON
// string, i.e. framed with braces. This way we are little bit more robust in
// case the tiddler contains unescaped texts "<data>" or "</data>". This must
// be changed when using a different stringifier.
var startTagText = "<data>{";
var endTagText = "}</data>";
var startPos = 0;
// Find the first not escaped "<data>".
var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
if (startDataTagIndex < 0) {
return null;
}
// Find the *last* not escaped "</data>".
var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
if (endDataTagIndex < 0) {
return null;
}
var nextEndDataTagIndex;
while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
endDataTagIndex = nextEndDataTagIndex;
}
return {
prefixEnd: startDataTagIndex,
dataStart: startDataTagIndex+(startTagText.length)-1,
dataEnd: endDataTagIndex,
suffixStart: endDataTagIndex+(endTagText.length)
};
};
// Internal.
//
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
var text = tiddler.text;
var info = DataTiddler.getDataSectionInfo(text);
if (!info) {
return null;
}
var prefix = text.substr(0,info.prefixEnd);
var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
var suffix = text.substr(info.suffixStart);
return [text, prefix, data, suffix];
};
// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change).
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected.
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send.
//
// This method should only be called when the data really has changed.
//
// @param tiddler
// the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
var prefix;
var suffix;
if (matches === null) {
prefix = tiddler.text;
suffix = "";
} else {
prefix = matches[1];
suffix = matches[3];
}
var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
var newText =
(dataText !== null)
? prefix + "<data>" + dataText + "</data>" + suffix
: prefix + suffix;
if (newText != tiddler.text) {
// make the change in the tiddlers text
// ... see DataTiddler.MyTiddlerChangedFunction
tiddler.isDataTiddlerChange = true;
// ... do the action change
tiddler.set(
tiddler.title,
newText,
config.options.txtUserName,
config.options.chkForceMinorUpdate? undefined : new Date(),
tiddler.tags);
// ... see DataTiddler.MyTiddlerChangedFunction
delete tiddler.isDataTiddlerChange;
// Mark the store as dirty.
store.dirty = true;
// AutoSave if option is selected
if(config.options.chkAutoSave) {
saveChanges();
}
}
};
// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
// Remove the data object from the tiddler when the tiddler is changed
// by code other than DataTiddler code.
//
// This is necessary since the data object is just a "cached version"
// of the data defined in the data section of the tiddler and the
// "external" change may have changed the content of the data section.
// Thus we are not sure if the data object reflects the data section
// contents.
//
// By deleting the data object we ensure that the data object is
// reconstructed the next time it is needed, with the data defined by
// the data section in the tiddler's text.
// To indicate that a change is a "DataTiddler change" a temporary
// property "isDataTiddlerChange" is added to the tiddler.
if (this.dataObject && !this.isDataTiddlerChange) {
delete this.dataObject;
}
// call the original code.
DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};
//============================================================================
// Formatters
//============================================================================
// This formatter ensures that "~<data>" is rendered as "<data>". This is used to
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
name: "data-escape",
match: "~<\\/?data>",
handler: function(w) {
w.outputText(w.output,w.matchStart + 1,w.nextMatch);
}
} );
// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
name: "data",
match: "<data>",
handler: function(w) {
var info = DataTiddler.getDataSectionInfo(w.source);
if (info && info.prefixEnd == w.matchStart) {
w.nextMatch = info.suffixStart;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
} );
//============================================================================
// Tiddler Class Extension
//============================================================================
// "Hijack" the changed method ---------------------------------------------------
DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;
// Define accessor methods -------------------------------------------------------
// Returns the value of the given data field of the tiddler. When no such field
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
return (field)
? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
: DataTiddler.getTiddlerDataObject(this);
};
// Sets the value of the given data field of the tiddler to the value. When the
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};
//============================================================================
// showData Macro
//============================================================================
config.macros.showData = {
// Standard Properties
label: "showData",
prompt: "Display the values stored in the data section of the tiddler"
};
config.macros.showData.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the optional "JSON"
var showInJSONFormat = false;
if ((i < params.length) && params[i] == "JSON") {
i++;
showInJSONFormat = true;
}
var tiddlerName = story.findContainingTiddler(place).id.substr(7);
if (i < params.length) {
tiddlerName = params[i];
i++;
}
// --- Processing ------------------------------------------
try {
if (showInJSONFormat) {
this.renderDataInJSONFormat(place, tiddlerName);
} else {
this.renderDataAsTable(place, tiddlerName);
}
} catch (e) {
this.createErrorElement(place, e);
}
};
config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
var text = DataTiddler.getDataText(tiddlerName);
if (text) {
createTiddlyElement(place,"pre",null,null,text);
}
};
config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
var text = "|!Name|!Value|\n";
var data = DataTiddler.getDataObject(tiddlerName);
if (data) {
for (var i in data) {
var value = data[i];
text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
}
}
wikify(text, place);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.showData.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".showDataError{color: #ffffff;background-color: #880000;}",
"showData");
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... TiddlyWiki Core
/*global createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global DataTiddler */
// ... JSON
/*global JSON */
/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
throw a 'JSONError' exception if there is an error.
*/
var JSON = {
copyright: '(c)2005 JSON.org',
license: 'http://www.crockford.com/JSON/license.html',
/*
Stringify a JavaScript value, producing a JSON text.
*/
stringify: function (v) {
var a = [];
/*
Emit a string.
*/
function e(s) {
a[a.length] = s;
}
/*
Convert a value.
*/
function g(x) {
var c, i, l, v;
switch (typeof x) {
case 'object':
if (x) {
if (x instanceof Array) {
e('[');
l = a.length;
for (i = 0; i < x.length; i += 1) {
v = x[i];
if (typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(v);
}
}
e(']');
return;
} else if (typeof x.toString != 'undefined') {
e('{');
l = a.length;
for (i in x) {
v = x[i];
if (x.hasOwnProperty(i) &&
typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(i);
e(':');
g(v);
}
}
return e('}');
}
}
e('null');
return;
case 'number':
e(isFinite(x) ? +x : 'null');
return;
case 'string':
l = x.length;
e('"');
for (i = 0; i < l; i += 1) {
c = x.charAt(i);
if (c >= ' ') {
if (c == '\\' || c == '"') {
e('\\');
}
e(c);
} else {
switch (c) {
case '\b':
e('\\b');
break;
case '\f':
e('\\f');
break;
case '\n':
e('\\n');
break;
case '\r':
e('\\r');
break;
case '\t':
e('\\t');
break;
default:
c = c.charCodeAt();
e('\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16));
}
}
}
e('"');
return;
case 'boolean':
e(String(x));
return;
default:
e('null');
return;
}
}
g(v);
return a.join('');
},
/*
Parse a JSON text, producing a JavaScript value.
*/
parse: function (text) {
var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
token,
operator;
function error(m, t) {
throw {
name: 'JSONError',
message: m,
text: t || operator || token
};
}
function next(b) {
if (b && b != operator) {
error("Expected '" + b + "'");
}
if (text) {
var t = p.exec(text);
if (t) {
if (t[2]) {
token = null;
operator = t[2];
} else {
operator = null;
try {
token = eval(t[1]);
} catch (e) {
error("Bad token", t[1]);
}
}
text = text.substring(t[0].length);
} else {
error("Unrecognized token", text);
}
} else {
token = operator = undefined;
}
}
function val() {
var k, o;
switch (operator) {
case '{':
next('{');
o = {};
if (operator != '}') {
for (;;) {
if (operator || typeof token != 'string') {
error("Missing key");
}
k = token;
next();
next(':');
o[k] = val();
if (operator != ',') {
break;
}
next(',');
}
}
next('}');
return o;
case '[':
next('[');
o = [];
if (operator != ']') {
for (;;) {
o.push(val());
if (operator != ',') {
break;
}
next(',');
}
}
next(']');
return o;
default:
if (operator !== null) {
error("Missing value");
}
k = token;
next();
return k;
}
}
next();
return val();
}
};
/***
!Setup the data serialization
***/
DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;
//}}}
/***
|Name|[[DatePlugin]]|
|Source|http://www.TiddlyTools.com/#DatePlugin|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.7.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|formatted dates plus popup menu with 'journal' link, changes and (optional) reminders|
This plugin provides a general approach to displaying formatted dates and/or links and popups that permit easy navigation and management of tiddlers based on their creation/modification dates.
!!!!!Documentation
>see [[DatePluginInfo]]
!!!!!Configuration
<<<
<<option chkDatePopupHideCreated>> omit 'created' section from date popups
<<option chkDatePopupHideChanged>> omit 'changed' section from date popups
<<option chkDatePopupHideTagged>> omit 'tagged' section from date popups
<<option chkDatePopupHideReminders>> omit 'reminders' section from date popups
<<option chkShowJulianDate>> display Julian day number (1-365) below current date
see [[DatePluginConfig]] for additional configuration settings, for use in calendar displays, including:
*date formats
*color-coded backgrounds
*annual fixed-date holidays
*weekends
<<<
!!!!!Revisions
<<<
2009.05.31 [2.7.1] in addRemindersToPopup(), 'new reminder....' command now uses {{{<<newTiddler>>}}} macro. Also, general code reduction/cleanup.
|please see [[DatePluginInfo]] for additional revision details|
2005.10.30 [0.9.0] pre-release
<<<
!!!!!Code
***/
//{{{
version.extensions.DatePlugin= {major: 2, minor: 7, revision: 1, date: new Date(2009,5,31)};
config.macros.date = {
format: 'YYYY.0MM.0DD', // default date display format
linkformat: 'YYYY.0MM.0DD', // 'dated tiddler' link format
linkedbg: '#babb1e', // 'babble'
todaybg: '#ffab1e', // 'fable'
weekendbg: '#c0c0c0', // 'cocoa'
holidaybg: '#ffaace', // 'face'
createdbg: '#bbeeff', // 'beef'
modifiedsbg: '#bbeeff', // 'beef'
remindersbg: '#c0ffee', // 'coffee'
weekend: [ 1,0,0,0,0,0,1 ], // [ day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 ],
holidays: [ '01/01', '07/04', '07/24', '11/24' ]
// NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)
};
config.macros.date.handler = function(place,macroName,params)
{
// default: display current date
var now =new Date();
var date=now;
var mode='display';
if (params[0]&&['display','popup','link'].contains(params[0].toLowerCase()))
{ mode=params[0]; params.shift(); }
if (!params[0] || params[0]=='today')
{ params.shift(); }
else if (params[0]=='filedate')
{ date=new Date(document.lastModified); params.shift(); }
else if (params[0]=='tiddler')
{ date=store.getTiddler(story.findContainingTiddler(place).id.substr(7)).modified; params.shift(); }
else if (params[0].substr(0,8)=='tiddler:')
{ var t; if ((t=store.getTiddler(params[0].substr(8)))) date=t.modified; params.shift(); }
else {
var y = eval(params.shift().replace(/Y/ig,(now.getYear()<1900)?now.getYear()+1900:now.getYear()));
var m = eval(params.shift().replace(/M/ig,now.getMonth()+1));
var d = eval(params.shift().replace(/D/ig,now.getDate()+0));
date = new Date(y,m-1,d);
}
// date format with optional custom override
var format=this.format; if (params[0]) format=params.shift();
var linkformat=this.linkformat; if (params[0]) linkformat=params.shift();
showDate(place,date,mode,format,linkformat);
}
window.showDate=showDate;
function showDate(place,date,mode,format,linkformat,autostyle,weekend)
{
mode =mode||'display';
format =format||config.macros.date.format;
linkformat=linkformat||config.macros.date.linkformat;
// format the date output
var title=date.formatString(format);
var linkto=date.formatString(linkformat);
// just show the formatted output
if (mode=='display') { place.appendChild(document.createTextNode(title)); return; }
// link to a 'dated tiddler'
var link = createTiddlyLink(place, linkto, false);
link.appendChild(document.createTextNode(title));
link.title = linkto;
link.date = date;
link.format = format;
link.linkformat = linkformat;
// if using a popup menu, replace click handler for dated tiddler link
// with handler for popup and make link text non-italic (i.e., an 'existing link' look)
if (mode=='popup') {
link.onclick = onClickDatePopup;
link.style.fontStyle='normal';
}
// format the popup link to show what kind of info it contains (for use with calendar generators)
if (autostyle) setDateStyle(place,link,weekend);
}
//}}}
//{{{
// NOTE: This function provides default logic for setting the date style when displayed in a calendar
// To customize the date style logic, please see[[DatePluginConfig]]
function setDateStyle(place,link,weekend) {
// alias variable names for code readability
var date=link.date;
var fmt=link.linkformat;
var linkto=date.formatString(fmt);
var cmd=config.macros.date;
if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=''))
{ place.style.background = cmd.weekendbg; }
if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
{ link.style.fontStyle='normal'; link.style.fontWeight='bold'; }
if (hasReminders(date))
{ link.style.textDecoration='underline'; }
if (isToday(date))
{ link.style.border='1px solid black'; }
if (isHoliday(date)&&(cmd.holidaybg!=''))
{ place.style.background = cmd.holidaybg; }
if (hasCreateds(date)&&(cmd.createdbg!=''))
{ place.style.background = cmd.createdbg; }
if (hasModifieds(date)&&(cmd.modifiedsbg!=''))
{ place.style.background = cmd.modifiedsbg; }
if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=''))
{ place.style.background = cmd.linkedbg; }
if (hasReminders(date)&&(cmd.remindersbg!=''))
{ place.style.background = cmd.remindersbg; }
if (isToday(date)&&(cmd.todaybg!=''))
{ place.style.background = cmd.todaybg; }
if (config.options.chkShowJulianDate) { // optional display of Julian date numbers
var m=[0,31,59,90,120,151,181,212,243,273,304,334];
var d=date.getDate()+m[date.getMonth()];
var y=date.getFullYear();
if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0)
d++; // after February in a leap year
wikify('@@font-size:80%;<br>'+d+'@@',place);
}
}
//}}}
//{{{
function isToday(date) // returns true if date is today
{ var now=new Date(); return ((now-date>=0) && (now-date<86400000)); }
function isWeekend(date) // returns true if date is a weekend
{ return (config.macros.date.weekend[date.getDay()]); }
function isHoliday(date) // returns true if date is a holiday
{
var longHoliday = date.formatString('0MM/0DD/YYYY');
var shortHoliday = date.formatString('0MM/0DD');
for(var i = 0; i < config.macros.date.holidays.length; i++) {
var holiday=config.macros.date.holidays[i];
if (holiday==longHoliday||holiday==shortHoliday) return true;
}
return false;
}
//}}}
//{{{
// Event handler for clicking on a day popup
function onClickDatePopup(e) { e=e||window.event;
var p=Popup.create(this); if (!p) return false;
// always show dated tiddler link (or just date, if readOnly) at the top...
if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))
createTiddlyLink(createTiddlyElement(p,'li'),this.date.formatString(this.linkformat),true);
else
createTiddlyText(createTiddlyElement(p,'li'),this.date.formatString(this.linkformat));
if (!config.options.chkDatePopupHideCreated)
addCreatedsToPopup(p,this.date,this.format);
if (!config.options.chkDatePopupHideChanged)
addModifiedsToPopup(p,this.date,this.format);
if (!config.options.chkDatePopupHideTagged)
addTaggedToPopup(p,this.date,this.linkformat);
if (!config.options.chkDatePopupHideReminders)
addRemindersToPopup(p,this.date,this.linkformat);
Popup.show(); e.cancelBubble=true; if(e.stopPropagation)e.stopPropagation(); return false;
}
//}}}
//{{{
function indexCreateds() // build list of tiddlers, hash indexed by creation date
{
var createds= { };
var tiddlers = store.getTiddlers('title','excludeLists');
for (var t = 0; t < tiddlers.length; t++) {
var date = tiddlers[t].created.formatString('YYYY0MM0DD')
if (!createds[date])
createds[date]=new Array();
createds[date].push(tiddlers[t].title);
}
return createds;
}
function hasCreateds(date) // returns true if date has created tiddlers
{
if (!config.macros.date.createds) config.macros.date.createds=indexCreateds();
return (config.macros.date.createds[date.formatString('YYYY0MM0DD')]!=undefined);
}
function addCreatedsToPopup(p,when,format)
{
var force=(store.isDirty() && when.formatString('YYYY0MM0DD')==new Date().formatString('YYYY0MM0DD'));
if (force || !config.macros.date.createds) config.macros.date.createds=indexCreateds();
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var createds = config.macros.date.createds[when.formatString('YYYY0MM0DD')];
if (createds) {
createds.sort();
var e=createTiddlyElement(p,'div',null,null,'created ('+createds.length+')');
for(var t=0; t<createds.length; t++) {
var link=createTiddlyLink(createTiddlyElement(p,'li'),createds[t],false);
link.appendChild(document.createTextNode(indent+createds[t]));
}
}
}
//}}}
//{{{
function indexModifieds() // build list of tiddlers, hash indexed by modification date
{
var modifieds= { };
var tiddlers = store.getTiddlers('title','excludeLists');
for (var t = 0; t < tiddlers.length; t++) {
var date = tiddlers[t].modified.formatString('YYYY0MM0DD')
if (!modifieds[date])
modifieds[date]=new Array();
modifieds[date].push(tiddlers[t].title);
}
return modifieds;
}
function hasModifieds(date) // returns true if date has modified tiddlers
{
if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();
return (config.macros.date.modifieds[date.formatString('YYYY0MM0DD')]!=undefined);
}
function addModifiedsToPopup(p,when,format)
{
var date=when.formatString('YYYY0MM0DD');
var force=(store.isDirty() && date==new Date().formatString('YYYY0MM0DD'));
if (force || !config.macros.date.modifieds) config.macros.date.modifieds=indexModifieds();
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var mods = config.macros.date.modifieds[date];
if (mods) {
// if a tiddler was created on this date, don't list it in the 'changed' section
if (config.macros.date.createds && config.macros.date.createds[date]) {
var temp=[];
for(var t=0; t<mods.length; t++)
if (!config.macros.date.createds[date].contains(mods[t]))
temp.push(mods[t]);
mods=temp;
}
mods.sort();
var e=createTiddlyElement(p,'div',null,null,'changed ('+mods.length+')');
for(var t=0; t<mods.length; t++) {
var link=createTiddlyLink(createTiddlyElement(p,'li'),mods[t],false);
link.appendChild(document.createTextNode(indent+mods[t]));
}
}
}
//}}}
//{{{
function hasTagged(date,format) // returns true if date is tagging other tiddlers
{
return store.getTaggedTiddlers(date.formatString(format)).length>0;
}
function addTaggedToPopup(p,when,format)
{
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var tagged=store.getTaggedTiddlers(when.formatString(format));
if (tagged.length) var e=createTiddlyElement(p,'div',null,null,'tagged ('+tagged.length+')');
for(var t=0; t<tagged.length; t++) {
var link=createTiddlyLink(createTiddlyElement(p,'li'),tagged[t].title,false);
link.appendChild(document.createTextNode(indent+tagged[t].title));
}
}
//}}}
//{{{
function indexReminders(date,leadtime) // build list of tiddlers with reminders, hash indexed by reminder date
{
var reminders = { };
if(window.findTiddlersWithReminders!=undefined) { // reminder plugin is installed
var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);
for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;
}
return reminders;
}
function hasReminders(date) // returns true if date has reminders
{
if (window.reminderCacheForCalendar)
return window.reminderCacheForCalendar[date]; // use calendar cache
if (!config.macros.date.reminders)
config.macros.date.reminders = indexReminders(date,90); // create a 90-day leadtime reminder cache
return (config.macros.date.reminders[date]);
}
function addRemindersToPopup(p,when,format)
{
if(window.findTiddlersWithReminders==undefined) return; // reminder plugin not installed
var indent = String.fromCharCode(160)+String.fromCharCode(160);
var reminders=findTiddlersWithReminders(when, [0,31],null,null,1);
createTiddlyElement(p,'div',null,null,'reminders ('+(reminders.length||'none')+')');
for(var t=0; t<reminders.length; t++) {
link = createTiddlyLink(createTiddlyElement(p,'li'),reminders[t].tiddler,false);
var diff=reminders[t].diff;
diff=(diff<1)?'Today':((diff==1)?'Tomorrow':diff+' days');
var txt=(reminders[t].params['title'])?reminders[t].params['title']:reminders[t].tiddler;
link.appendChild(document.createTextNode(indent+diff+' - '+txt));
}
if (readOnly) return; // readonly... omit 'new reminder...' command
var rem='\\<\\<reminder day:%0 month:%1 year:%2 title:"Enter a reminder title here"\\>\\>';
rem=rem.format([when.getDate(),when.getMonth()+1,when.getYear()+1900]);
var cmd="<<newTiddler label:[["+indent+"new reminder...]] prompt:[[add a reminder to '%0']]"
+" title:[[%0]] text:{{var t=store.getTiddlerText('%0','');t+(t.length?'\\n':'')+'%1'}} tag:%2>>";
wikify(cmd.format([when.formatString(format),rem,config.options.txtCalendarReminderTags||'']),
createTiddlyElement(p,'li'));
}
//}}}
/***
|Name|DatePluginConfig|
|Source|http://www.TiddlyTools.com/#DatePluginConfig|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.6.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|formats, background colors and other optional settings for DatePlugin|
***/
// // Default popup content display options (can be overridden by cookies)
//{{{
if (config.options.chkDatePopupHideCreated===undefined)
config.options.chkDatePopupHideCreated=false;
if (config.options.chkDatePopupHideChanged===undefined)
config.options.chkDatePopupHideChanged=false;
if (config.options.chkDatePopupHideTagged===undefined)
config.options.chkDatePopupHideTagged=false;
if (config.options.chkDatePopupHideReminders===undefined)
config.options.chkDatePopupHideReminders=false;
//}}}
// // show Julian date number below regular date
//{{{
if (config.options.chkShowJulianDate===undefined)
config.options.chkShowJulianDate=false;
//}}}
// // fixed-date annual holidays
//{{{
config.macros.date.holidays=[
"01/01", // NewYearsDay,
"07/04", // US Independence Day
"07/24" // Eric's Birthday (hooray!)
];
//}}}
// // weekend map (1=weekend, 0=weekday)
//{{{
config.macros.date.weekend=[ 1,0,0,0,0,0,1 ]; // day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6
//}}}
// // date display/link formats
//{{{
config.macros.date.format="YYYY.0MM.0DD"; // default date display format
config.macros.date.linkformat="YYYY.0MM.0DD"; // 'dated tiddler' link format
//}}}
// // When displaying a calendar (see [[CalendarPlugin]]), you can customize the colors/styles that are applied to the calendar dates by modifying the values and/or functions below:
//{{{
// default calendar colors
config.macros.date.weekendbg="#c0c0c0";
config.macros.date.holidaybg="#ffaace";
config.macros.date.createdbg="#bbeeff";
config.macros.date.modifiedsbg="#bbeeff";
config.macros.date.linkedbg="#babb1e";
config.macros.date.remindersbg="#c0ffee";
// apply calendar styles
function setDateStyle(place,link,weekend) {
// alias variable names for code readability
var date=link.date;
var fmt=link.linkformat;
var linkto=date.formatString(fmt);
var cmd=config.macros.date;
if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
{ place.style.background = cmd.weekendbg; }
if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
if (hasReminders(date))
{ link.style.textDecoration="underline"; }
if (isToday(date))
{ link.style.border="1px solid black"; }
if (isHoliday(date)&&(cmd.holidaybg!=""))
{ place.style.background = cmd.holidaybg; }
if (hasCreateds(date)&&(cmd.createdbg!=""))
{ place.style.background = cmd.createdbg; }
if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
{ place.style.background = cmd.modifiedsbg; }
if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
{ place.style.background = cmd.linkedbg; }
if (hasReminders(date)&&(cmd.remindersbg!=""))
{ place.style.background = cmd.remindersbg; }
if (isToday(date)&&(cmd.todaybg!=""))
{ place.style.background = cmd.todaybg; }
if (config.options.chkShowJulianDate) {
var m=[0,31,59,90,120,151,181,212,243,273,304,334];
var d=date.getDate()+m[date.getMonth()];
var y=date.getFullYear();
if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0) d++; // after February in a leap year
wikify("@@font-size:80%;<br>"+d+"@@",place);
}
}
//}}}
<<infobox
Type:"Example Person"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Hair color:"test1"
Eye color:"test1"
Skin color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Wrong Type"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Person"
>>
<<infobox
Type:"Example Battle"
img:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Date:"test1"
loc:"shorthandtest1"
Outcome:"test1"
Previous:"test1"
Next:"test1"
gcommanders:"shorthandtest1left"
bcommanders:"shorthandtest1right"
gstrength:"shorthandtest1left"
bstrength:"shorthandtest1right"
Side1-Good_casualties:"test1left"
Side2-Bad_casualties:"test1right"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
>>
<<infobox
Type:"Example Person"
InstanceID:"test2"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
<<infobox
Type:"Example Person"
InstanceID:"test3"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test3"
Born:"test3"
Died:"test3"
Species:"test3"
Gender:"test3"
>>
<<infobox
Type:"Example Person"
InstanceID:"test4"
Homeworld:"test4"
Died:"test4"
Species:"test4"
Height:"test4"
Hair_color:"test4"
Skin_color:"test4"
Eras:"test4"
Known_masters:"test4"
>>
<<infobox
Type:"Example Battle"
InstanceID:"test5"
img:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Date:"test1"
loc:"test1"
Outcome:"test1"
Previous:"test1"
Concurrent:"test1"
Next:"test1"
gfighters:"shorthandtest1left"
bfighters:"shorthandtest1right"
gcommanders:"shorthandtest1left"
bcommanders:"shorthandtest1right"
gstrength:"shorthandtest1left"
bstrength:"shorthandtest1right"
Side1-Good_casualties:"test1left"
Side2-Bad_casualties:"test1right"
>>
<<infobox
Type:"Example Battle"
InstanceID:"test6"
img:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Date:"test2"
loc:"test2"
Outcome:"test2"
Previous:"test2"
Next:"test2"
bfighters:"shorthandtest1right"
gstrength:"shorthandtest1left"
Side1-Good_casualties:"test1left"
Side2-Bad_casualties:"test1right"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Person"
InstanceID:"test2"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Species:"test2"
Gender:"test2"
Height:"test2"
Hair_color:"test2"
Eye_color:"test2"
Skin_color:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
<<infobox
Type:"Example Person"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test23
Born:"test3"
Died:"test3"
Species:"test3"
Gender:"test3"
Height:"test3"
Hair_color:"test3"
Eye_color:"test3"
Skin_color:"test3"
Eras:"test3"
Affiliation:"test3"
Known_masters:"test3"
Known_apprentices:"test3"
>>
<<tiddler [[Example with two infoboxes with and without a custom title]]>>
<<infobox
Type:"Example Person"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Battle"
img:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Date:"test1"
loc:"test1"
Previous:"test1"
Next:"test1"
gfighters:"shorthandtest1left"
bfighters:"shorthandtest1right"
gstrength:"shorthandtest1left"
bstrength:"shorthandtest1right"
Side1-Good_casualties:"test1left"
Side2-Bad_casualties:"test1right"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Person"
InstanceID:"test2"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Species:"test2"
Gender:"test2"
Height:"test2"
Skin_color:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Species:"test1"
Gender:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin color:"test1"
Eras:"test1"
Affiliation:"test1"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Species:"test2"
Gender:"test2"
Eye_color:"test2"
Skin_color:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
<<infobox
Type:"Example Person"
InstanceID:"test1"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Person"
InstanceID:"test2"
Title:"This is a custom title"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Species:"test2"
Gender:"test2"
Height:"test2"
Hair_color:"test2"
Eye_color:"test2"
Skin_color:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
<<infobox
Type:"Example Person"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test1"
Born:"test1"
Died:"test1"
Species:"test1"
Gender:"test1"
Height:"test1"
Hair_color:"test1"
Eye_color:"test1"
Skin_color:"test1"
Eras:"test1"
Affiliation:"test1"
Known_masters:"test1"
Known_apprentices:"test1"
>>
<<infobox
Type:"Example Person"
Image-Person:"http://www.google.com/logos/2012/childrensday-2012-hp.jpg"
Homeworld:"test2"
Born:"test2"
Died:"test2"
Species:"test2"
Gender:"test2"
Height:"test2"
Hair_color:"test2"
Eye_color:"test2"
Skin_color:"test2"
Eras:"test2"
Affiliation:"test2"
Known_masters:"test2"
Known_apprentices:"test2"
>>
|timelineHeight:|250|
|band0.width:|70%|
|band0.intervalUnit:|MONTH|
|band0.intervalPixels:|100|
|band0.date:|Jun 28 2006|
|band0.eventSourceType:|tiddlerSlices|
|band0.eventSourceParams:|SimileExample1Timeline|
|band1.width:|30%|
|band1.intervalUnit:|YEAR|
|band1.intervalPixels:|200|
|band1.date:|Jun 28 2006|
|band1.highlight:|true|
|band1.eventSourceType:|tiddlerSlices|
|band1.eventSourceParams:|SimileExample1Timeline|
|band1.showEventText:|false|
|band1.trackHeight:|0.5|
|band1.trackGap:|0.2|
|timelineHeight:|250|
|band0.width:|70%|
|band0.zones:|zones0|
|band0.intervalUnit:|MONTH|
|band0.intervalPixels:|100|
|band0.date:|Jun 28 2006|
|band0.eventSourceType:|tiddlerSlices|
|band0.eventSourceParams:|SimileExample2Timeline|
|band1.width:|30%|
|band1.zones:|zones1|
|band1.intervalUnit:|YEAR|
|band1.intervalPixels:|200|
|band1.date:|Jun 28 2006|
|band1.highlight:|true|
|band1.eventSourceType:|tiddlerSlices|
|band1.eventSourceParams:|SimileExample2Timeline|
|band1.showEventText:|false|
|band1.trackHeight:|0.5|
|band1.trackGap:|0.2|
zones0 = [
{start: "Aug 01 2006 00:00:00 GMT-0500",
end: "Sep 01 2006 00:00:00 GMT-0500",
magnify:10,
unit: Timeline.DateTime.WEEK
},
{start: "Aug 02 2006 00:00:00 GMT-0500",
end: "Aug 04 2006 00:00:00 GMT-0500",
magnify:7,
unit: Timeline.DateTime.DAY
},
{start: "Aug 02 2006 06:00:00 GMT-0500",
end: "Aug 02 2006 12:00:00 GMT-0500",
magnify:5,
unit: Timeline.DateTime.HOUR
}
];
zones1 = [
{start: "Aug 01 2006 00:00:00 GMT-0500",
end: "Sep 01 2006 00:00:00 GMT-0500",
magnify:20,
unit: Timeline.DateTime.WEEK
}
];
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactively select/export tiddlers to a separate file|
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2011.02.14 2.9.6 fix OSX error: use picker.file.path
2010.02.25 2.9.5 added merge checkbox option and improved 'merge' status message
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 0.0.0 development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 9, revision: 6, date: new Date(2011,2,14)};
// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';
// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
config.tasks.exportTask = {
text:'export',
tooltip:'Export selected tiddlers to another file',
content:'<<exportTiddlers inline>>'
}
config.backstageTasks.splice(config.backstageTasks.indexOf('importTask')+1,0,'exportTask');
}
config.macros.exportTiddlers = {
$: function(id) { return document.getElementById(id); }, // abbreviation
label: 'export tiddlers',
prompt: 'Copy selected tiddlers to an export document',
okmsg: '%0 tiddler%1 written to %2',
failmsg: 'An error occurred while creating %1',
overwriteprompt: '%0\ncontains %1 tiddler%2 that will be discarded or replaced',
mergestatus: '%0 tiddler%1 added, %2 tiddler%3 updated, %4 tiddler%5 unchanged',
statusmsg: '%0 tiddler%1 - %2 selected for export',
newdefault: 'export.html',
datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss', // for 'filter date/time' edit fields
type_TW: "tw", type_PS: "ps", type_TX: "tx", type_CS: "cs", type_NF: "nf", // file type tokens
type_map: { // maps type param to token values
tiddlywiki:"tw", tw:"tw", wiki: "tw",
purestore: "ps", ps:"ps", store:"ps",
plaintext: "tx", tx:"tx", text: "tx",
comma: "cs", cs:"cs", csv: "cs",
newsfeed: "nf", nf:"nf", xml: "nf", rss:"nf"
},
handler: function(place,macroName,params) {
if (params[0]!='inline')
{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
var panel=this.createPanel(place);
panel.style.position='static';
panel.style.display='block';
},
createPanel: function(place) {
var panel=this.$('exportPanel');
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(store.getTiddlerText('ExportTiddlersPlugin##css',''),'exportTiddlers');
panel=createTiddlyElement(place,'span','exportPanel',null,null)
panel.innerHTML=store.getTiddlerText('ExportTiddlersPlugin##html','');
this.initFilter();
this.refreshList(0);
var fn=this.$('exportFilename');
if (window.location.protocol=='file:' && !fn.value.length) {
// get new target path/filename
var newPath=getLocalPath(window.location.href);
var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\');
if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
fn.value=newPath+this.newdefault;
}
return panel;
},
togglePanel: function(e) { var e=e||window.event;
var cme=config.macros.exportTiddlers; // abbrev
var parent=resolveTarget(e).parentNode;
var panel=cme.$('exportPanel');
if (panel==undefined || panel.parentNode!=parent)
panel=cme.createPanel(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') {
cme.refreshList(0);
cme.$('exportFilename').focus();
cme.$('exportFilename').select();
}
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
},
process: function(which) { // process panel control interactions
var theList=this.$('exportList'); if (!theList) return false;
var count = 0;
var total = store.getTiddlers('title').length;
switch (which.id) {
case 'exportFilter':
count=this.filterExportList();
var panel=this.$('exportFilterPanel');
if (count==-1) { panel.style.display='block'; break; }
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
break;
case 'exportStart':
this.go();
break;
case 'exportDelete':
this.deleteTiddlers();
break;
case 'exportHideFilter':
case 'exportToggleFilter':
var panel=this.$('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;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(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;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,count);
break;
case 'exportSelectOpened':
for (var t=0; t<theList.options.length; t++) theList.options[t].selected=false;
var tiddlerDisplay=this.$('tiddlerDisplay');
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;
}
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) alert('There are no tiddlers currently opened');
break;
case 'exportSelectRelated':
// recursively build list of related tiddlers
function getRelatedTiddlers(tid,tids) {
var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
tids.push(t.title);
if (!t.linksUpdated) t.changed();
for (var i=0; i<t.links.length; i++)
if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
return tids;
}
// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
var tids=[];
for (var i=0; i<theList.options.length; i++)
if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
// select related tiddlers (includes original selected tiddlers)
for (var i=0; i<theList.options.length; i++)
theList.options[i].selected=tids.contains(theList.options[i].value);
this.displayStatus(tids.length,total);
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':
this.$('exportPanel').style.display='none';
break;
}
return false;
},
displayStatus: function(count,total) {
var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
clearMessage(); displayMessage(txt);
return txt;
},
refreshList: function(selectedIndex) {
var theList = this.$('exportList'); if (!theList) return;
// get the sort order
var sort;
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
var count=0;
for (var t=5; 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' and 'delete' buttons if no tiddlers selected
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
// show selection count
var tiddlers = store.getTiddlers('title');
if (theList.options.length) this.displayStatus(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
this.$('exportStart').disabled=true;
this.$('exportDelete').disabled=true;
this.displayStatus(0,tiddlers.length);
},
askForFilename: function(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 filetype=this.$('exportFormat').value.toLowerCase();
var defext='html';
if (filetype==this.type_TX) defext='txt';
if (filetype==this.type_CS) defext='csv';
if (filetype==this.type_NF) defext='xml';
var file=this.newdefault.replace(/html$/,defext);
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=defext;
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.path;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XPSP2 IE only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
s.FilterIndex=defext=='txt'?2:'html'?3:'xml'?4:1;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { // fallback
var result=prompt(msg,path+file);
}
}
return result;
},
initFilter: function() {
this.$('exportFilterStart').checked=false; this.$('exportStartDate').value='';
this.$('exportFilterEnd').checked=false; this.$('exportEndDate').value='';
this.$('exportFilterTags').checked=false; this.$('exportTags').value='';
this.$('exportFilterText').checked=false; this.$('exportText').value='';
this.showFilterFields();
},
showFilterFields: function(which) {
var show=this.$('exportFilterStart').checked;
this.$('exportFilterStartBy').style.display=show?'block':'none';
this.$('exportStartDate').style.display=show?'block':'none';
var val=this.$('exportFilterStartBy').value;
this.$('exportStartDate').value
=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterStartBy') && (val=='other'))
this.$('exportStartDate').focus();
var show=this.$('exportFilterEnd').checked;
this.$('exportFilterEndBy').style.display=show?'block':'none';
this.$('exportEndDate').style.display=show?'block':'none';
var val=this.$('exportFilterEndBy').value;
this.$('exportEndDate').value
=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterEndBy') && (val=='other'))
this.$('exportEndDate').focus();
var show=this.$('exportFilterTags').checked;
this.$('exportTags').style.display=show?'block':'none';
var show=this.$('exportFilterText').checked;
this.$('exportText').style.display=show?'block':'none';
},
getFilterDate: function(val,id) {
var result=0;
switch (val) {
case 'file':
result=new Date(document.lastModified);
break;
case 'other':
result=new Date(this.$(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;
}
return result;
},
filterExportList: function() {
var theList = this.$('exportList'); if (!theList) return -1;
var filterStart=this.$('exportFilterStart').checked;
var val=this.$('exportFilterStartBy').value;
var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
var filterEnd=this.$('exportFilterEnd').checked;
var val=this.$('exportFilterEndBy').value;
var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
var filterTags=this.$('exportFilterTags').checked;
var tags=this.$('exportTags').value;
var filterText=this.$('exportFilterText').checked;
var text=this.$('exportText').value;
if (!(filterStart||filterEnd||filterTags||filterText)) {
alert('Please set the selection filter');
this.$('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;
}
// if filter by tags, get list of matching tiddlers
// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
// otherwise use getTaggedTiddlers() for simple tag matching
if (filterTags) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var t=fn.apply(store,[tags]);
var tagged=[];
for (var i=0; i<t.length; i++) tagged.push(t[i].title);
}
// 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 && !tagged.contains(tiddler.title))
|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
sel=false;
opt.selected=sel;
count+=sel?1:0;
total++;
}
return count;
},
deleteTiddlers: function() {
var list=this.$('exportList'); if (!list) return;
var tids=[];
for (i=0;i<list.length;i++)
if (list.options[i].selected && list.options[i].value.length)
tids.push(list.options[i].value);
if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
store.suspendNotifications();
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
msg+='Removing this tiddler may cause unexpected results. Are you sure?'
if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
store.removeTiddler(tid.title);
story.closeTiddler(tid.title);
}
store.resumeNotifications();
alert(tids.length+' tiddlers deleted');
this.refreshList(0); // reload listbox
store.notifyAll(); // update page display
},
go: function() {
if (window.location.protocol!='file:') // make sure we are local
{ displayMessage(config.messages.notFileUrlError); return; }
// get selected tidders, target filename, target type, and notes
var list=this.$('exportList'); if (!list) return;
var tids=[]; for (var i=0; i<list.options.length; i++) {
var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
var tid=store.getTiddler(opt.value); if (!tid) continue;
tids.push(tid);
}
if (!tids.length) return; // no tiddlers selected
var target=this.$('exportFilename').value.trim();
if (!target.length) {
displayMessage('A local target path/filename is required',target);
return;
}
var merge=this.$('exportMerge').checked;
var filetype=this.$('exportFormat').value.toLowerCase();
var notes=this.$('exportNotes').value.replace(/\n/g,'<br>');
var total={val:0};
var out=this.assembleFile(target,filetype,tids,notes,total,merge);
if (!total.val) return; // cancelled file overwrite
var link='file:///'+target.replace(/\\/g,'/');
var samefile=link==decodeURIComponent(window.location.href);
var p=getLocalPath(document.location.href);
if (samefile) {
if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
}
var ok=saveFile(target,out);
displayMessage((ok?this.okmsg:this.failmsg).format([total.val,total.val!=1?'s':'',target]),link);
},
plainTextHeader:
'Source:\n\t%0\n'
+'Title:\n\t%1\n'
+'Subtitle:\n\t%2\n'
+'Created:\n\t%3 by %4\n'
+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
plainTextTiddler:
'- - - - - - - - - - - - - - -\n'
+'| title: %0\n'
+'| created: %1\n'
+'| modified: %2\n'
+'| edited by: %3\n'
+'| tags: %4\n'
+'- - - - - - - - - - - - - - -\n'
+'%5\n',
plainTextFooter:
'',
newsFeedHeader:
'<'+'?xml version="1.0"?'+'>\n'
+'<rss version="2.0">\n'
+'<channel>\n'
+'<title>%1</title>\n'
+'<link>%0</link>\n'
+'<description>%2</description>\n'
+'<language>en-us</language>\n'
+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
+'<pubDate>%3</pubDate>\n'
+'<lastBuildDate>%3</lastBuildDate>\n'
+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
newsFeedTiddler:
'\n%0\n',
newsFeedFooter:
'</channel></rss>',
pureStoreHeader:
'<html><body>'
+'<style type="text/css">'
+' #storeArea {display:block;margin:1em;}'
+' #storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
+' #pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
+'</style>'
+'<div id="pureStoreHeading">'
+' TiddlyWiki "PureStore" export file<br>'
+' Source'+': <b>%0</b><br>'
+' Title: <b>%1</b><br>'
+' Subtitle: <b>%2</b><br>'
+' Created: <b>%3</b> by <b>%4</b><br>'
+' TiddlyWiki %5 / %6 %7<br>'
+' Notes:<hr><pre>%8</pre>'
+'</div>'
+'<div id="storeArea">',
pureStoreTiddler:
'%0\n%1',
pureStoreFooter:
'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
assembleFile: function(target,filetype,tids,notes,total,merge) {
var revised='';
var now = new Date().toLocaleString();
var src=convertUnicodeToUTF8(document.location.href);
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 v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
switch (filetype) {
case this.type_TX: // plain text
var header=this.plainTextHeader.format(headerargs);
var footer=this.plainTextFooter;
break;
case this.type_CS: // comma-separated
var fields={};
for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
var names=['title','created','modified','modifier','tags','text'];
for (var f in fields) names.push(f);
var header=names.join(',')+'\n';
var footer='';
break;
case this.type_NF: // news feed (XML)
headerargs[0]=store.getTiddlerText('SiteUrl','');
var header=this.newsFeedHeader.format(headerargs);
var footer=this.newsFeedFooter;
break;
case this.type_PS: // PureStore (no code)
var header=this.pureStoreHeader.format(headerargs);
var footer=this.pureStoreFooter;
break;
case this.type_TW: // full TiddlyWiki
default:
var currPath=getLocalPath(window.location.href);
var original=loadFile(currPath);
if (!original) { displayMessage(config.messages.cantSaveError); return; }
var posDiv = locateStoreArea(original);
if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
var footer = '\n'+original.substr(posDiv[1]);
break;
}
var out=this.getData(target,filetype,tids,fields,merge);
var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
// if full TW, insert page title and language attr, and reset all MARKUP blocks...
if (filetype==this.type_TW) {
var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
revised=updateLanguageAttribute(revised);
var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
revised=updateMarkupBlock(revised,'PRE-HEAD',
titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
revised=updateMarkupBlock(revised,'POST-HEAD',
titles.contains('MarkupPostHead')?'MarkupPostHead':null);
revised=updateMarkupBlock(revised,'PRE-BODY',
titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
revised=updateMarkupBlock(revised,'POST-SCRIPT',
titles.contains('MarkupPostBody')?'MarkupPostBody':null);
}
total.val=out.length;
return revised;
},
getData: function(target,filetype,tids,fields,merge) {
// output selected tiddlers and gather list of titles (for use with merge)
var out=[]; var titles=[];
var url=store.getTiddlerText('SiteUrl','');
for (var i=0; i<tids.length; i++) {
out.push(this.formatItem(store,filetype,tids[i],url,fields));
titles.push(tids[i].title);
}
// if TW or PureStore format, ask to merge with existing tiddlers (if any)
if (filetype==this.type_TW || filetype==this.type_PS) {
var txt=loadFile(target);
if (txt && txt.length) {
var remoteStore=new TiddlyWiki();
if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
if (remoteStore.importTiddlyWiki(txt)) {
var existing=remoteStore.getTiddlers('title');
var msg=this.overwriteprompt.format([target,existing.length,existing.length!=1?'s':'']);
if (merge) {
var added=titles.length; var updated=0; var kept=0;
for (var i=0; i<existing.length; i++)
if (titles.contains(existing[i].title)) {
added--; updated++;
} else {
out.push(this.formatItem(remoteStore,filetype,existing[i],url));
kept++;
}
displayMessage(this.mergestatus.format(
[added,added!=1?'s':'',updated,updated!=1?'s':'',kept,kept!=1?'s':'',]));
}
else if (!confirm(msg)) out=[]; // empty the list = don't write file
}
}
}
return out;
},
formatItem: function(s,f,t,u,fields) {
if (f==this.type_TW)
var r=s.getSaver().externalizeTiddler(s,t);
if (f==this.type_PS)
var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
if (f==this.type_NF)
var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
if (f==this.type_TX)
var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
if (f==this.type_CS) {
function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
for (var f in fields) out.push(toCSV(t.fields[f]||''));
var r=out.join(',');
}
return r||"";
}
}
//}}}
/***
!!!Control panel CSS
//{{{
!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;-webkit-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;-webkit-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%; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- target path/file -->
<div>
<div style="float:right;padding-right:.5em">
<input type="checkbox" style="width:auto" id="exportMerge" CHECKED
title="combine selected tiddlers with existing tiddlers (if any) in export file"> merge
</div>
export to:<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="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">
</div>
<!-- output format -->
<div>
format:
<select id="exportFormat" size=1>
<option value="TW">TiddlyWiki HTML document (includes core code)</option>
<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>
<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>
<option value="CS">Comma-Separated Value (CSV) data file</option>
<option value="NF">RSS NewsFeed XML file</option>
</select>
</div>
<!-- notes -->
<div>
notes:<br>
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea>
</div>
<!-- list of tiddlers -->
<table><tr align="left"><td>
select:
<a href="JavaScript:;" id="exportSelectAll"
onclick="return config.macros.exportTiddlers.process(this)" title="select all tiddlers">
all </a>
<a href="JavaScript:;" id="exportSelectChanges"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">
changes </a>
<a href="JavaScript:;" id="exportSelectOpened"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">
opened </a>
<a href="JavaScript:;" id="exportSelectRelated"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">
related </a>
<a href="JavaScript:;" id="exportToggleFilter"
onclick="return config.macros.exportTiddlers.process(this)" title="show/hide selection filter">
filter </a>
</td><td align="right">
<a href="JavaScript:;" id="exportListSmaller"
onclick="return config.macros.exportTiddlers.process(this)" title="reduce list size">
– </a>
<a href="JavaScript:;" id="exportListLarger"
onclick="return config.macros.exportTiddlers.process(this)" title="increase list size">
+ </a>
</td></tr></table>
<select id="exportList" multiple size="10" style="margin-bottom:5px;"
onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">
</select><br>
<!-- 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="return config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>
</td></tr></table>
<div class="box">
<input type="checkbox" class="chk" id="exportFilterStart" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterStartBy"
onchange="config.macros.exportTiddlers.showFilterFields(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="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="config.macros.exportTiddlers.$('exportFilterStartBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterEndBy"
onchange="config.macros.exportTiddlers.showFilterFields(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="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="config.macros.exportTiddlers.$('exportFilterEndBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id=exportFilterTags value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>
<input type="text" id="exportTags" onfocus="this.select()">
<input type="checkbox" class="chk" id=exportFilterText value="1"
onclick="config.macros.exportTiddlers.showFilterFields(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="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportFilter" value="apply filter">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportStart" value="export tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportDelete" value="delete tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportClose" value="close">
</div><!--center-->
!end
//}}}
***/
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactively select/export tiddlers to a separate file|
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2010.02.25 2.9.5 added merge checkbox option and improved 'merge' status message
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 0.0.0 development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 9, revision: 5, date: new Date(2010,2,25)};
// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';
// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
config.tasks.exportTask = {
text:'export',
tooltip:'Export selected tiddlers to another file',
content:'<<exportTiddlers inline>>'
}
config.backstageTasks.splice(config.backstageTasks.indexOf('importTask')+1,0,'exportTask');
}
config.macros.exportTiddlers = {
$: function(id) { return document.getElementById(id); }, // abbreviation
label: 'export tiddlers',
prompt: 'Copy selected tiddlers to an export document',
okmsg: '%0 tiddler%1 written to %2',
failmsg: 'An error occurred while creating %1',
overwriteprompt: '%0\ncontains %1 tiddler%2 that will be discarded or replaced',
mergestatus: '%0 tiddler%1 added, %2 tiddler%3 updated, %4 tiddler%5 unchanged',
statusmsg: '%0 tiddler%1 - %2 selected for export',
newdefault: 'export.html',
datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss', // for 'filter date/time' edit fields
type_TW: "tw", type_PS: "ps", type_TX: "tx", type_CS: "cs", type_NF: "nf", // file type tokens
type_map: { // maps type param to token values
tiddlywiki:"tw", tw:"tw", wiki: "tw",
purestore: "ps", ps:"ps", store:"ps",
plaintext: "tx", tx:"tx", text: "tx",
comma: "cs", cs:"cs", csv: "cs",
newsfeed: "nf", nf:"nf", xml: "nf", rss:"nf"
},
handler: function(place,macroName,params) {
if (params[0]!='inline')
{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
var panel=this.createPanel(place);
panel.style.position='static';
panel.style.display='block';
},
createPanel: function(place) {
var panel=this.$('exportPanel');
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(store.getTiddlerText('ExportTiddlersPlugin##css',''),'exportTiddlers');
panel=createTiddlyElement(place,'span','exportPanel',null,null)
panel.innerHTML=store.getTiddlerText('ExportTiddlersPlugin##html','');
this.initFilter();
this.refreshList(0);
var fn=this.$('exportFilename');
if (window.location.protocol=='file:' && !fn.value.length) {
// get new target path/filename
var newPath=getLocalPath(window.location.href);
var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\');
if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
fn.value=newPath+this.newdefault;
}
return panel;
},
togglePanel: function(e) { var e=e||window.event;
var cme=config.macros.exportTiddlers; // abbrev
var parent=resolveTarget(e).parentNode;
var panel=cme.$('exportPanel');
if (panel==undefined || panel.parentNode!=parent)
panel=cme.createPanel(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') {
cme.refreshList(0);
cme.$('exportFilename').focus();
cme.$('exportFilename').select();
}
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
},
process: function(which) { // process panel control interactions
var theList=this.$('exportList'); if (!theList) return false;
var count = 0;
var total = store.getTiddlers('title').length;
switch (which.id) {
case 'exportFilter':
count=this.filterExportList();
var panel=this.$('exportFilterPanel');
if (count==-1) { panel.style.display='block'; break; }
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
break;
case 'exportStart':
this.go();
break;
case 'exportDelete':
this.deleteTiddlers();
break;
case 'exportHideFilter':
case 'exportToggleFilter':
var panel=this.$('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;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(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;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,count);
break;
case 'exportSelectOpened':
for (var t=0; t<theList.options.length; t++) theList.options[t].selected=false;
var tiddlerDisplay=this.$('tiddlerDisplay');
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;
}
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) alert('There are no tiddlers currently opened');
break;
case 'exportSelectRelated':
// recursively build list of related tiddlers
function getRelatedTiddlers(tid,tids) {
var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
tids.push(t.title);
if (!t.linksUpdated) t.changed();
for (var i=0; i<t.links.length; i++)
if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
return tids;
}
// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
var tids=[];
for (var i=0; i<theList.options.length; i++)
if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
// select related tiddlers (includes original selected tiddlers)
for (var i=0; i<theList.options.length; i++)
theList.options[i].selected=tids.contains(theList.options[i].value);
this.displayStatus(tids.length,total);
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':
this.$('exportPanel').style.display='none';
break;
}
return false;
},
displayStatus: function(count,total) {
var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
clearMessage(); displayMessage(txt);
return txt;
},
refreshList: function(selectedIndex) {
var theList = this.$('exportList'); if (!theList) return;
// get the sort order
var sort;
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
var count=0;
for (var t=5; 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' and 'delete' buttons if no tiddlers selected
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
// show selection count
var tiddlers = store.getTiddlers('title');
if (theList.options.length) this.displayStatus(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
this.$('exportStart').disabled=true;
this.$('exportDelete').disabled=true;
this.displayStatus(0,tiddlers.length);
},
askForFilename: function(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 filetype=this.$('exportFormat').value.toLowerCase();
var defext='html';
if (filetype==this.type_TX) defext='txt';
if (filetype==this.type_CS) defext='csv';
if (filetype==this.type_NF) defext='xml';
var file=this.newdefault.replace(/html$/,defext);
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=defext;
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 { // XPSP2 IE only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
s.FilterIndex=defext=='txt'?2:'html'?3:'xml'?4:1;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { // fallback
var result=prompt(msg,path+file);
}
}
return result;
},
initFilter: function() {
this.$('exportFilterStart').checked=false; this.$('exportStartDate').value='';
this.$('exportFilterEnd').checked=false; this.$('exportEndDate').value='';
this.$('exportFilterTags').checked=false; this.$('exportTags').value='';
this.$('exportFilterText').checked=false; this.$('exportText').value='';
this.showFilterFields();
},
showFilterFields: function(which) {
var show=this.$('exportFilterStart').checked;
this.$('exportFilterStartBy').style.display=show?'block':'none';
this.$('exportStartDate').style.display=show?'block':'none';
var val=this.$('exportFilterStartBy').value;
this.$('exportStartDate').value
=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterStartBy') && (val=='other'))
this.$('exportStartDate').focus();
var show=this.$('exportFilterEnd').checked;
this.$('exportFilterEndBy').style.display=show?'block':'none';
this.$('exportEndDate').style.display=show?'block':'none';
var val=this.$('exportFilterEndBy').value;
this.$('exportEndDate').value
=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterEndBy') && (val=='other'))
this.$('exportEndDate').focus();
var show=this.$('exportFilterTags').checked;
this.$('exportTags').style.display=show?'block':'none';
var show=this.$('exportFilterText').checked;
this.$('exportText').style.display=show?'block':'none';
},
getFilterDate: function(val,id) {
var result=0;
switch (val) {
case 'file':
result=new Date(document.lastModified);
break;
case 'other':
result=new Date(this.$(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;
}
return result;
},
filterExportList: function() {
var theList = this.$('exportList'); if (!theList) return -1;
var filterStart=this.$('exportFilterStart').checked;
var val=this.$('exportFilterStartBy').value;
var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
var filterEnd=this.$('exportFilterEnd').checked;
var val=this.$('exportFilterEndBy').value;
var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
var filterTags=this.$('exportFilterTags').checked;
var tags=this.$('exportTags').value;
var filterText=this.$('exportFilterText').checked;
var text=this.$('exportText').value;
if (!(filterStart||filterEnd||filterTags||filterText)) {
alert('Please set the selection filter');
this.$('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;
}
// if filter by tags, get list of matching tiddlers
// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
// otherwise use getTaggedTiddlers() for simple tag matching
if (filterTags) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var t=fn.apply(store,[tags]);
var tagged=[];
for (var i=0; i<t.length; i++) tagged.push(t[i].title);
}
// 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 && !tagged.contains(tiddler.title))
|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
sel=false;
opt.selected=sel;
count+=sel?1:0;
total++;
}
return count;
},
deleteTiddlers: function() {
var list=this.$('exportList'); if (!list) return;
var tids=[];
for (i=0;i<list.length;i++)
if (list.options[i].selected && list.options[i].value.length)
tids.push(list.options[i].value);
if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
store.suspendNotifications();
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
msg+='Removing this tiddler may cause unexpected results. Are you sure?'
if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
store.removeTiddler(tid.title);
story.closeTiddler(tid.title);
}
store.resumeNotifications();
alert(tids.length+' tiddlers deleted');
this.refreshList(0); // reload listbox
store.notifyAll(); // update page display
},
go: function() {
if (window.location.protocol!='file:') // make sure we are local
{ displayMessage(config.messages.notFileUrlError); return; }
// get selected tidders, target filename, target type, and notes
var list=this.$('exportList'); if (!list) return;
var tids=[]; for (var i=0; i<list.options.length; i++) {
var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
var tid=store.getTiddler(opt.value); if (!tid) continue;
tids.push(tid);
}
if (!tids.length) return; // no tiddlers selected
var target=this.$('exportFilename').value.trim();
if (!target.length) {
displayMessage('A local target path/filename is required',target);
return;
}
var merge=this.$('exportMerge').checked;
var filetype=this.$('exportFormat').value.toLowerCase();
var notes=this.$('exportNotes').value.replace(/\n/g,'<br>');
var total={val:0};
var out=this.assembleFile(target,filetype,tids,notes,total,merge);
if (!total.val) return; // cancelled file overwrite
var link='file:///'+target.replace(/\\/g,'/');
var samefile=link==decodeURIComponent(window.location.href);
var p=getLocalPath(document.location.href);
if (samefile) {
if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
}
var ok=saveFile(target,out);
displayMessage((ok?this.okmsg:this.failmsg).format([total.val,total.val!=1?'s':'',target]),link);
},
plainTextHeader:
'Source:\n\t%0\n'
+'Title:\n\t%1\n'
+'Subtitle:\n\t%2\n'
+'Created:\n\t%3 by %4\n'
+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
plainTextTiddler:
'- - - - - - - - - - - - - - -\n'
+'| title: %0\n'
+'| created: %1\n'
+'| modified: %2\n'
+'| edited by: %3\n'
+'| tags: %4\n'
+'- - - - - - - - - - - - - - -\n'
+'%5\n',
plainTextFooter:
'',
newsFeedHeader:
'<'+'?xml version="1.0"?'+'>\n'
+'<rss version="2.0">\n'
+'<channel>\n'
+'<title>%1</title>\n'
+'<link>%0</link>\n'
+'<description>%2</description>\n'
+'<language>en-us</language>\n'
+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
+'<pubDate>%3</pubDate>\n'
+'<lastBuildDate>%3</lastBuildDate>\n'
+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
newsFeedTiddler:
'\n%0\n',
newsFeedFooter:
'</channel></rss>',
pureStoreHeader:
'<html><body>'
+'<style type="text/css">'
+' #storeArea {display:block;margin:1em;}'
+' #storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
+' #pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
+'</style>'
+'<div id="pureStoreHeading">'
+' TiddlyWiki "PureStore" export file<br>'
+' Source'+': <b>%0</b><br>'
+' Title: <b>%1</b><br>'
+' Subtitle: <b>%2</b><br>'
+' Created: <b>%3</b> by <b>%4</b><br>'
+' TiddlyWiki %5 / %6 %7<br>'
+' Notes:<hr><pre>%8</pre>'
+'</div>'
+'<div id="storeArea">',
pureStoreTiddler:
'%0\n%1',
pureStoreFooter:
'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
assembleFile: function(target,filetype,tids,notes,total,merge) {
var revised='';
var now = new Date().toLocaleString();
var src=convertUnicodeToUTF8(document.location.href);
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 v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
switch (filetype) {
case this.type_TX: // plain text
var header=this.plainTextHeader.format(headerargs);
var footer=this.plainTextFooter;
break;
case this.type_CS: // comma-separated
var fields={};
for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
var names=['title','created','modified','modifier','tags','text'];
for (var f in fields) names.push(f);
var header=names.join(',')+'\n';
var footer='';
break;
case this.type_NF: // news feed (XML)
headerargs[0]=store.getTiddlerText('SiteUrl','');
var header=this.newsFeedHeader.format(headerargs);
var footer=this.newsFeedFooter;
break;
case this.type_PS: // PureStore (no code)
var header=this.pureStoreHeader.format(headerargs);
var footer=this.pureStoreFooter;
break;
case this.type_TW: // full TiddlyWiki
default:
var currPath=getLocalPath(window.location.href);
var original=loadFile(currPath);
if (!original) { displayMessage(config.messages.cantSaveError); return; }
var posDiv = locateStoreArea(original);
if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
var footer = '\n'+original.substr(posDiv[1]);
break;
}
var out=this.getData(target,filetype,tids,fields,merge);
var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
// if full TW, insert page title and language attr, and reset all MARKUP blocks...
if (filetype==this.type_TW) {
var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
revised=updateLanguageAttribute(revised);
var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
revised=updateMarkupBlock(revised,'PRE-HEAD',
titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
revised=updateMarkupBlock(revised,'POST-HEAD',
titles.contains('MarkupPostHead')?'MarkupPostHead':null);
revised=updateMarkupBlock(revised,'PRE-BODY',
titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
revised=updateMarkupBlock(revised,'POST-SCRIPT',
titles.contains('MarkupPostBody')?'MarkupPostBody':null);
}
total.val=out.length;
return revised;
},
getData: function(target,filetype,tids,fields,merge) {
// output selected tiddlers and gather list of titles (for use with merge)
var out=[]; var titles=[];
var url=store.getTiddlerText('SiteUrl','');
for (var i=0; i<tids.length; i++) {
out.push(this.formatItem(store,filetype,tids[i],url,fields));
titles.push(tids[i].title);
}
// if TW or PureStore format, ask to merge with existing tiddlers (if any)
if (filetype==this.type_TW || filetype==this.type_PS) {
var txt=loadFile(target);
if (txt && txt.length) {
var remoteStore=new TiddlyWiki();
if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
if (remoteStore.importTiddlyWiki(txt)) {
var existing=remoteStore.getTiddlers('title');
var msg=this.overwriteprompt.format([target,existing.length,existing.length!=1?'s':'']);
if (merge) {
var added=titles.length; var updated=0; var kept=0;
for (var i=0; i<existing.length; i++)
if (titles.contains(existing[i].title)) {
added--; updated++;
} else {
out.push(this.formatItem(remoteStore,filetype,existing[i],url));
kept++;
}
displayMessage(this.mergestatus.format(
[added,added!=1?'s':'',updated,updated!=1?'s':'',kept,kept!=1?'s':'',]));
}
else if (!confirm(msg)) out=[]; // empty the list = don't write file
}
}
}
return out;
},
formatItem: function(s,f,t,u,fields) {
if (f==this.type_TW)
var r=s.getSaver().externalizeTiddler(s,t);
if (f==this.type_PS)
var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
if (f==this.type_NF)
var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
if (f==this.type_TX)
var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
if (f==this.type_CS) {
function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
for (var f in fields) out.push(toCSV(t.fields[f]||''));
var r=out.join(',');
}
return r||"";
}
}
//}}}
/***
!!!Control panel CSS
//{{{
!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;-webkit-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;-webkit-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%; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- target path/file -->
<div>
<div style="float:right;padding-right:.5em">
<input type="checkbox" style="width:auto" id="exportMerge" CHECKED
title="combine selected tiddlers with existing tiddlers (if any) in export file"> merge
</div>
export to:<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="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">
</div>
<!-- output format -->
<div>
format:
<select id="exportFormat" size=1>
<option value="TW">TiddlyWiki HTML document (includes core code)</option>
<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>
<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>
<option value="CS">Comma-Separated Value (CSV) data file</option>
<option value="NF">RSS NewsFeed XML file</option>
</select>
</div>
<!-- notes -->
<div>
notes:<br>
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea>
</div>
<!-- list of tiddlers -->
<table><tr align="left"><td>
select:
<a href="JavaScript:;" id="exportSelectAll"
onclick="return config.macros.exportTiddlers.process(this)" title="select all tiddlers">
all </a>
<a href="JavaScript:;" id="exportSelectChanges"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">
changes </a>
<a href="JavaScript:;" id="exportSelectOpened"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">
opened </a>
<a href="JavaScript:;" id="exportSelectRelated"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">
related </a>
<a href="JavaScript:;" id="exportToggleFilter"
onclick="return config.macros.exportTiddlers.process(this)" title="show/hide selection filter">
filter </a>
</td><td align="right">
<a href="JavaScript:;" id="exportListSmaller"
onclick="return config.macros.exportTiddlers.process(this)" title="reduce list size">
– </a>
<a href="JavaScript:;" id="exportListLarger"
onclick="return config.macros.exportTiddlers.process(this)" title="increase list size">
+ </a>
</td></tr></table>
<select id="exportList" multiple size="10" style="margin-bottom:5px;"
onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">
</select><br>
<!-- 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="return config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>
</td></tr></table>
<div class="box">
<input type="checkbox" class="chk" id="exportFilterStart" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterStartBy"
onchange="config.macros.exportTiddlers.showFilterFields(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="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="config.macros.exportTiddlers.$('exportFilterStartBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterEndBy"
onchange="config.macros.exportTiddlers.showFilterFields(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="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="config.macros.exportTiddlers.$('exportFilterEndBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id=exportFilterTags value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>
<input type="text" id="exportTags" onfocus="this.select()">
<input type="checkbox" class="chk" id=exportFilterText value="1"
onclick="config.macros.exportTiddlers.showFilterFields(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="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportFilter" value="apply filter">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportStart" value="export tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportDelete" value="delete tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportClose" value="close">
</div><!--center-->
!end
//}}}
***/
version.extensions.FlickrGreetingMacro = { major: 1, minor: 0, revision: 1, date: new Date(2006,3,24) };
config.macros.flickrGreetingCookie = {};
config.macros.flickrGreetingCookie.handler = function (place,name,params) {
wikify("<<flickrGreeting " + config.options.txtUserName + ">>", place);
}
config.macros.flickrGreeting = {};
config.macros.flickrGreeting.handler = function (place,name,params) {
//List of greetings:
var WelcomeMessage = [
"Hola",
"Hala",
"Shalom",
"Ni hao",
"Kumusta",
"'Allo",
"G'day",
"Hoi",
"Giorno",
"Hi",
"Hej",
"Olá",
"Ahoy",
"Salut",
"Hello",
"Hoi",
"Oi",
"Hoi",
"Aloha",
"Bonjour",
"Guten Tag",
"Yo",
"Shalom",
"Namaste",
"Ciao"
];
//randomness:
var index = Math.floor(Math.random() * WelcomeMessage.length);
//output:
var who = params.length > 0 ? (" "+params[0]) : "";
wikify(WelcomeMessage[index] + who /* + "!" */, place);
}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|© 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description
Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.
''Syntax:''
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].
!Revision history
* v1.0.8 (2007-04-12)
** Adapted to latest TiddlyWiki 2.2 Beta importTiddlyWiki API (introduced with changeset 2004). TiddlyWiki 2.2 Beta builds prior to changeset 2004 are no longer supported (but TiddlyWiki 2.1 and earlier, of cause)
* v1.0.7 (2007-03-28)
** Also support "pre" formatted TiddlyWikis (introduced with TW 2.2) (when using "in" clause to work on external tiddlers)
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features:
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen)
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features:
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs:
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features:
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// ForEachTiddlerPlugin
//============================================================================
//============================================================================
// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {
if (!window.abego) window.abego = {};
version.extensions.ForEachTiddlerPlugin = {
major: 1, minor: 0, revision: 8,
date: new Date(2007,3,12),
source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};
// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
TiddlyWiki.prototype.forEachTiddler = function(callback) {
for(var t in this.tiddlers) {
callback.call(this,t,this.tiddlers[t]);
}
};
}
//============================================================================
// forEachTiddler Macro
//============================================================================
version.extensions.forEachTiddler = {
major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
config.macros.forEachTiddler = {
// Standard Properties
label: "forEachTiddler",
prompt: "Perform actions on a (sorted) selection of tiddlers",
// actions
actions: {
addToList: {},
write: {}
}
};
// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler
// ---------------------------------------------------------------------------
config.macros.forEachTiddler.getContainingTiddler = function(e) {
while(e && !hasClass(e,"tiddler"))
e = e.parentNode;
var title = e ? e.getAttribute("tiddler") : null;
return title ? store.getTiddler(title) : null;
};
config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);
if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the "in" clause
var tiddlyWikiPath = undefined;
if ((i < params.length) && params[i] == "in") {
i++;
if (i >= params.length) {
this.handleError(place, "TiddlyWiki path expected behind 'in'.");
return;
}
tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the where clause
var whereClause ="true";
if ((i < params.length) && params[i] == "where") {
i++;
whereClause = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the sort stuff
var sortClause = null;
var sortAscending = true;
if ((i < params.length) && params[i] == "sortBy") {
i++;
if (i >= params.length) {
this.handleError(place, "sortClause missing behind 'sortBy'.");
return;
}
sortClause = this.paramEncode(params[i]);
i++;
if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
sortAscending = params[i] == "ascending";
i++;
}
}
// Parse the script
var scriptText = null;
if ((i < params.length) && params[i] == "script") {
i++;
scriptText = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the action.
// When we are already at the end use the default action
var actionName = "addToList";
if (i < params.length) {
if (!config.macros.forEachTiddler.actions[params[i]]) {
this.handleError(place, "Unknown action '"+params[i]+"'.");
return;
} else {
actionName = params[i];
i++;
}
}
// Get the action parameter
// (the parsing is done inside the individual action implementation.)
var actionParameter = params.slice(i);
// --- Processing ------------------------------------------
try {
this.performMacro({
place: place,
inTiddler: tiddler,
whereClause: whereClause,
sortClause: sortClause,
sortAscending: sortAscending,
actionName: actionName,
actionParameter: actionParameter,
scriptText: scriptText,
tiddlyWikiPath: tiddlyWikiPath});
} catch (e) {
this.handleError(place, e);
}
};
// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {
var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);
var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
context["tiddlyWiki"] = tiddlyWiki;
// Get the tiddlers, as defined by the whereClause
var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
context["tiddlers"] = tiddlers;
// Sort the tiddlers, when sorting is required.
if (parameter.sortClause) {
this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
}
return {tiddlers: tiddlers, context: context};
};
// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
return this.getTiddlersAndContext(parameter).tiddlers;
};
// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
//
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
//
// All properties are optional.
// For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
var tiddlersAndContext = this.getTiddlersAndContext(parameter);
// Perform the action
var actionName = parameter.actionName ? parameter.actionName : "addToList";
var action = config.macros.forEachTiddler.actions[actionName];
if (!action) {
this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
return;
}
var actionHandler = action.handler;
actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};
// ---------------------------------------------------------------------------
// The actions
// ---------------------------------------------------------------------------
// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
return;
}
// Perform the action.
var list = document.createElement("ul");
place.appendChild(list);
for (var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var listItem = document.createElement("li");
list.appendChild(listItem);
createTiddlyLink(listItem, tiddler.title, true);
}
};
abego.parseNamedParameter = function(name, parameter, i) {
var beginExpression = null;
if ((i < parameter.length) && parameter[i] == name) {
i++;
if (i >= parameter.length) {
throw "Missing text behind '%0'".format([name]);
}
return config.macros.forEachTiddler.paramEncode(parameter[i]);
}
return null;
}
// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
if (p >= parameter.length) {
this.handleError(place, "Missing expression behind 'write'.");
return;
}
var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
// Parse the "begin" option
var beginExpression = abego.parseNamedParameter("begin", parameter, p);
if (beginExpression !== null)
p += 2;
var endExpression = abego.parseNamedParameter("end", parameter, p);
if (endExpression !== null)
p += 2;
var noneExpression = abego.parseNamedParameter("none", parameter, p);
if (noneExpression !== null)
p += 2;
// Parse the "toFile" option
var filename = null;
var lineSeparator = undefined;
if ((p < parameter.length) && parameter[p] == "toFile") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
return;
}
filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
p++;
if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
return;
}
lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
}
}
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
return;
}
// Perform the action.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
var count = tiddlers.length;
var text = "";
if (count > 0 && beginExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
for (var i = 0; i < count; i++) {
var tiddler = tiddlers[i];
text += func(tiddler, context, count, i);
}
if (count > 0 && endExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);
if (count == 0 && noneExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
if (filename) {
if (lineSeparator !== undefined) {
lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
text = text.replace(/\n/mg,lineSeparator);
}
saveFile(filename, convertUnicodeToUTF8(text));
} else {
var wrapper = createTiddlyElement(place, "span");
wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
}
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
return {
place : placeParam,
whereClause : whereClauseParam,
sortClause : sortClauseParam,
sortAscending : sortAscendingParam,
script : scriptText,
actionName : actionNameParam,
actionParameter : actionParameterParam,
tiddlyWikiPath : tiddlyWikiPathParam,
inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
};
};
// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
if (!idPrefix) {
idPrefix = "store";
}
var lenPrefix = idPrefix.length;
// Read the content of the given file
var content = loadFile(this.getLocalPath(path));
if(content === null) {
throw "TiddlyWiki '"+path+"' not found.";
}
var tiddlyWiki = new TiddlyWiki();
// Starting with TW 2.2 there is a helper function to import the tiddlers
if (tiddlyWiki.importTiddlyWiki) {
if (!tiddlyWiki.importTiddlyWiki(content))
throw "File '"+path+"' is not a TiddlyWiki.";
tiddlyWiki.dirty = false;
return tiddlyWiki;
}
// The legacy code, for TW < 2.2
// Locate the storeArea div's
var posOpeningDiv = content.indexOf(startSaveArea);
var posClosingDiv = content.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
throw "File '"+path+"' is not a TiddlyWiki.";
}
var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
// Create a "div" element that contains the storage text
var myStorageDiv = document.createElement("div");
myStorageDiv.innerHTML = storageText;
myStorageDiv.normalize();
// Create all tiddlers in a new TiddlyWiki
// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
var store = myStorageDiv.childNodes;
for(var t = 0; t < store.length; t++) {
var e = store[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
title = e.id.substr(lenPrefix);
if(title && title !== "") {
var tiddler = tiddlyWiki.createTiddler(title);
tiddler.loadFromDiv(e,title);
}
}
tiddlyWiki.dirty = false;
return tiddlyWiki;
};
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
//
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
var script = context["script"];
var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
var fullText = (script ? script+";" : "")+functionText+";theFunction;";
return eval(fullText);
};
// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
var result = [];
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
tiddlyWiki.forEachTiddler(function(title,tiddler) {
if (func(tiddler, context, undefined, undefined)) {
result.push(tiddler);
}
});
return result;
};
// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
var message = "Extra parameter behind '"+actionName+"':";
for (var i = firstUnusedIndex; i < parameter.length; i++) {
message += " "+parameter[i];
}
this.handleError(place, message);
};
// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? -1
: +1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? +1
: -1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
// To avoid evaluating the sortClause whenever two items are compared
// we pre-calculate the sortValue for every item in the array and store it in a
// temporary property ("forEachTiddlerSortValue") of the tiddlers.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
var count = tiddlers.length;
var i;
for (i = 0; i < count; i++) {
var tiddler = tiddlers[i];
tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
}
// Do the sorting
tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);
// Delete the temporary property that holds the sortValue.
for (i = 0; i < tiddlers.length; i++) {
delete tiddlers[i].forEachTiddlerSortValue;
}
};
// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
displayMessage(message);
};
// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
var message ="<<"+macroName;
for (var i = 0; i < params.length; i++) {
message += " "+params[i];
}
message += ">>";
displayMessage(message);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};
// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
if (place) {
this.createErrorElement(place, exception);
} else {
throw exception;
}
};
// Internal.
//
// Encodes the given string.
//
// Replaces
// "$))" to ">>"
// "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
var reGTGT = new RegExp("\\$\\)\\)","mg");
var reGT = new RegExp("\\$\\)","mg");
return s.replace(reGTGT, ">>").replace(reGT, ">");
};
// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
//
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
// 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"),"\\");
return localPath;
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
"forEachTiddler");
//============================================================================
// End of forEachTiddler Macro
//============================================================================
//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
var n = prefix.length;
return (this.length >= n) && (this.slice(0, n) == prefix);
};
//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
var n = suffix.length;
return (this.length >= n) && (this.right(n) == suffix);
};
//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
return this.indexOf(substring) >= 0;
};
//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] == item) {
return i;
}
}
return -1;
};
//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false.
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
return (this.indexOf(item) >= 0);
};
//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
for(var i = 0; i < items.length; i++) {
if (this.contains(items[i])) {
return true;
}
}
return false;
};
//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
//
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null]
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
for(var i = 0; i < items.length; i++) {
if (!this.contains(items[i])) {
return false;
}
}
return true;
};
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink,
displayMessage, endSaveArea, hasClass, loadFile, saveFile,
startSaveArea, store, wikify */
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
/***
<<checkForDataTiddlerPlugin>>
|''Name:''|FormTiddlerPlugin|
|''Version:''|1.0.6 (2007-06-24)|
|''Source:''|http://tiddlywiki.abego-software.de/#FormTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|formTiddler, checkForDataTiddlerPlugin, newTiddlerWithForm|
|''Requires:''|DataTiddlerPlugin|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Use form-based tiddlers to enter your tiddler data using text fields, listboxes, checkboxes etc. (All standard HTML Form input elements supported).
''Syntax:''
|>|{{{<<}}}''formTiddler'' //tiddlerName//{{{>>}}}|
|//tiddlerName//|The name of the FormTemplate tiddler to be used to edit the data of the tiddler containing the macro.|
|>|{{{<<}}}''newTiddlerWithForm'' //formTemplateName// //buttonLabel// [//titleExpression// [''askUser'']] {{{>>}}}|
|//formTemplateName//|The name of the tiddler that defines the form the new tiddler should use.|
|//buttonLabel//|The label of the button|
|//titleExpression//|A (quoted) JavaScript String expression that defines the title (/name) of the new tiddler.|
|''askUser''|Typically the user is not asked for the title when a title is specified (and not yet used). When ''askUser'' is given the user will be asked in any case. This may be used when the calculated title is just a suggestion that must be confirmed by the user|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
For details and how to use the macros see the [[introduction|FormTiddler Introduction]] and the [[examples|FormTiddler Examples]].
!Revision history
* v1.0.6 (2007-06-24)
** Fixed problem when using SELECT component in Internet Explorer (thanks to MaikBoenig for reporting)
* v1.0.5 (2006-02-24)
** Removed "debugger;" instruction
* v1.0.4 (2006-02-07)
** Bug: On IE no data is written to data section when field values changed (thanks to KenGirard for reporting)
* v1.0.3 (2006-02-05)
** Bug: {{{"No form template specified in <<formTiddler>>"}}} when using formTiddler macro on InternetExplorer (thanks to KenGirard for reporting)
* v1.0.2 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.1 (2005-12-22)
** Features:
*** Support InternetExplorer
*** Added newTiddlerWithForm Macro
* v1.0.0 (2005-12-14)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// FormTiddlerPlugin
//============================================================================
//============================================================================
if (!window.abego) window.abego = {};
abego.getOptionsValue = function(element,i) {
var v = element.options[i].value;
if (!v && element.options[i].text)
v = element.options[i].text;
return v;
};
version.extensions.FormTiddlerPlugin = {
major: 1, minor: 0, revision: 5,
date: new Date(2006, 2, 24),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#FormTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; }
//============================================================================
// formTiddler Macro
//============================================================================
// -------------------------------------------------------------------------------
// Configurations and constants
// -------------------------------------------------------------------------------
config.macros.formTiddler = {
// Standard Properties
label: "formTiddler",
version: {major: 1, minor: 0, revision: 4, date: new Date(2006, 2, 7)},
prompt: "Edit tiddler data using forms",
// Define the "setters" that set the values of INPUT elements of a given type
// (must match the corresponding "getter")
setter: {
button: function(e, value) {/*contains no data */ },
checkbox: function(e, value) {e.checked = value;},
file: function(e, value) {try {e.value = value;} catch(e) {/* ignore, possibly security error*/}},
hidden: function(e, value) {e.value = value;},
password: function(e, value) {e.value = value;},
radio: function(e, value) {e.checked = (e.value == value);},
reset: function(e, value) {/*contains no data */ },
"select-one": function(e, value) {config.macros.formTiddler.setSelectOneValue(e,value);},
"select-multiple": function(e, value) {config.macros.formTiddler.setSelectMultipleValue(e,value);},
submit: function(e, value) {/*contains no data */},
text: function(e, value) {e.value = value;},
textarea: function(e, value) {e.value = value;}
},
// Define the "getters" that return the value of INPUT elements of a given type
// Return undefined to not store any data.
getter: {
button: function(e, value) {return undefined;},
checkbox: function(e, value) {return e.checked;},
file: function(e, value) {return e.value;},
hidden: function(e, value) {return e.value;},
password: function(e, value) {return e.value;},
radio: function(e, value) {return e.checked ? e.value : undefined;},
reset: function(e, value) {return undefined;},
"select-one": function(e, value) {return config.macros.formTiddler.getSelectOneValue(e);},
"select-multiple": function(e, value) {return config.macros.formTiddler.getSelectMultipleValue(e);},
submit: function(e, value) {return undefined;},
text: function(e, value) {return e.value;},
textarea: function(e, value) {return e.value;}
}
};
// -------------------------------------------------------------------------------
// The formTiddler Macro Handler
// -------------------------------------------------------------------------------
config.macros.formTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
if (!config.macros.formTiddler.checkForExtensions(place, macroName)) {
return;
}
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// get the name of the form template tiddler
var formTemplateName = undefined;
if (i < params.length) {
formTemplateName = params[i];
i++;
}
if (!formTemplateName) {
config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
return;
}
// --- Processing ------------------------------------------
// Get the form template text.
// (This contains the INPUT elements for the form.)
var formTemplateTiddler = store.getTiddler(formTemplateName);
if (!formTemplateTiddler) {
config.macros.formTiddler.createErrorElement(place, "Form template '" + formTemplateName + "' not found.");
return;
}
var templateText = formTemplateTiddler.text;
if(!templateText) {
// Shortcut: when template text is empty we do nothing.
return;
}
// Get the name of the tiddler containing this "formTiddler" macro
// (i.e. the tiddler, that will be edited and that contains the data)
var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(place);
// Append a "form" element.
var formName = "form"+formTemplateName+"__"+tiddlerName;
var e = document.createElement("form");
e.setAttribute("name", formName);
place.appendChild(e);
// "Embed" the elements defined by the templateText (i.e. the INPUT elements)
// into the "form" element we just created
wikify(templateText, e);
// Initialize the INPUT elements.
config.macros.formTiddler.initValuesAndHandlersInFormElements(formName, DataTiddler.getDataObject(tiddlerName));
}
// -------------------------------------------------------------------------------
// Form Data Access
// -------------------------------------------------------------------------------
// Internal.
//
// Initialize the INPUT elements of the form with the values of their "matching"
// data fields in the tiddler. Also setup the onChange handler to ensure that
// changes in the INPUT elements are stored in the tiddler's data.
//
config.macros.formTiddler.initValuesAndHandlersInFormElements = function(formName, data) {
// config.macros.formTiddler.trace("initValuesAndHandlersInFormElements(formName="+formName+", data="+data+")");
// find the form
var form = config.macros.formTiddler.findForm(formName);
if (!form) {
return;
}
try {
var elems = form.elements;
for (var i = 0; i < elems.length; i++) {
var c = elems[i];
var setter = config.macros.formTiddler.setter[c.type];
if (setter) {
var value = data[c.name];
if (value != null) {
setter(c, value);
}
c.onchange = onFormTiddlerChange;
} else {
config.macros.formTiddler.displayFormTiddlerError("No setter defined for INPUT element of type '"+c.type+"'. (Element '"+c.name+"' in form '"+formName+"')");
}
}
} catch(e) {
config.macros.formTiddler.displayFormTiddlerError("Error when updating elements with new formData. "+e);
}
}
// Internal.
//
// @return [may be null]
//
config.macros.formTiddler.findForm = function(formName) {
// We must manually iterate through the document's forms, since
// IE does not support the "document[formName]" approach
var forms = window.document.forms;
for (var i = 0; i < forms.length; i++) {
var form = forms[i];
if (form.name == formName) {
return form;
}
}
return null;
}
// Internal.
//
config.macros.formTiddler.setSelectOneValue = function(element,value) {
var n = element.options.length;
for (var i = 0; i < n; i++) {
element.options[i].selected = abego.getOptionsValue(element,i) == value;
}
}
// Internal.
//
config.macros.formTiddler.setSelectMultipleValue = function(element,value) {
var values = {};
for (var i = 0; i < value.length; i++) {
values[value[i]] = true;
}
var n = element.length;
for (var i = 0; i < n; i++) {
element.options[i].selected = !(!values[abego.getOptionsValue(element,i)]);
}
}
// Internal.
//
config.macros.formTiddler.getSelectOneValue = function(element) {
var i = element.selectedIndex;
return (i >= 0) ? abego.getOptionsValue(element,i) : null;
}
// Internal.
//
config.macros.formTiddler.getSelectMultipleValue = function(element) {
var values = [];
var n = element.length;
for (var i = 0; i < n; i++) {
if (element.options[i].selected) {
values.push(abego.getOptionsValue(element,i));
}
}
return values;
}
// -------------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------------
// Internal.
//
config.macros.formTiddler.checkForExtensions = function(place,macroName) {
if (!version.extensions.DataTiddlerPlugin) {
config.macros.formTiddler.createErrorElement(place, "<<" + macroName + ">> requires the DataTiddlerPlugin. (You can get it from http://tiddlywiki.abego-software.de/#DataTiddlerPlugin)");
return false;
}
return true;
}
// Internal.
//
// Displays a trace message in the "TiddlyWiki" message pane.
// (used for debugging)
//
config.macros.formTiddler.trace = function(s) {
displayMessage("Trace: "+s);
}
// Internal.
//
// Display some error message in the "TiddlyWiki" message pane.
//
config.macros.formTiddler.displayFormTiddlerError = function(s) {
alert("FormTiddlerPlugin Error: "+s);
}
// Internal.
//
// Creates an element that holds an error message
//
config.macros.formTiddler.createErrorElement = function(place, message) {
return createTiddlyElement(place,"span",null,"formTiddlerError",message);
}
// Internal.
//
// Returns the name of the tiddler containing the given element.
//
config.macros.formTiddler.getContainingTiddlerName = function(element) {
return story.findContainingTiddler(element).id.substr(7);
}
// -------------------------------------------------------------------------------
// Event Handlers
// -------------------------------------------------------------------------------
// This function must be called by the INPUT elements whenever their
// data changes. Typically this is done through an "onChange" handler.
//
function onFormTiddlerChange (e) {
// config.macros.formTiddler.trace("onFormTiddlerChange "+e);
if (!e) var e = window.event;
var target = resolveTarget(e);
var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(target);
var getter = config.macros.formTiddler.getter[target.type];
if (getter) {
var value = getter(target);
DataTiddler.setData(tiddlerName, target.name, value);
} else {
config.macros.formTiddler.displayFormTiddlerError("No getter defined for INPUT element of type '"+target.type+"'. (Element '"+target.name+"' used in tiddler '"+tiddlerName+"')");
}
}
// ensure that the function can be used in HTML event handler
window.onFormTiddlerChange = onFormTiddlerChange;
// -------------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// -------------------------------------------------------------------------------
setStylesheet(
".formTiddlerError{color: #ffffff;background-color: #880000;}",
"formTiddler");
//============================================================================
// checkForDataTiddlerPlugin Macro
//============================================================================
config.macros.checkForDataTiddlerPlugin = {
// Standard Properties
label: "checkForDataTiddlerPlugin",
version: {major: 1, minor: 0, revision: 0, date: new Date(2005, 12, 14)},
prompt: "Check if the DataTiddlerPlugin exists"
}
config.macros.checkForDataTiddlerPlugin.handler = function(place,macroName,params) {
config.macros.formTiddler.checkForExtensions(place, config.macros.formTiddler.label);
}
//============================================================================
// newTiddlerWithForm Macro
//============================================================================
config.macros.newTiddlerWithForm = {
// Standard Properties
label: "newTiddlerWithForm",
version: {major: 1, minor: 0, revision: 1, date: new Date(2006, 1, 6)},
prompt: "Creates a new Tiddler with a <<formTiddler ...>> macro"
}
config.macros.newTiddlerWithForm.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// get the name of the form template tiddler
var formTemplateName = undefined;
if (i < params.length) {
formTemplateName = params[i];
i++;
}
if (!formTemplateName) {
config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
return;
}
// get the button label
var buttonLabel = undefined;
if (i < params.length) {
buttonLabel = params[i];
i++;
}
if (!buttonLabel) {
config.macros.formTiddler.createErrorElement(place, "No button label specified in <<" + macroName + ">>.");
return;
}
// get the (optional) tiddlerName script and "askUser"
var tiddlerNameScript = undefined;
var askUser = false;
if (i < params.length) {
tiddlerNameScript = params[i];
i++;
if (i < params.length && params[i] == "askUser") {
askUser = true;
i++;
}
}
// --- Processing ------------------------------------------
if(!readOnly) {
var onClick = function() {
var tiddlerName;
if (tiddlerNameScript) {
try {
tiddlerName = eval(tiddlerNameScript);
} catch (ex) {
}
}
if (!tiddlerName || askUser) {
tiddlerName = prompt("Please specify a tiddler name.", askUser ? tiddlerName : "");
}
while (tiddlerName && store.getTiddler(tiddlerName)) {
tiddlerName = prompt("A tiddler named '"+tiddlerName+"' already exists.\n\n"+"Please specify a tiddler name.", tiddlerName);
}
// tiddlerName is either null (user canceled) or a name that is not yet in the store.
if (tiddlerName) {
var body = "<<formTiddler [["+formTemplateName+"]]>>";
var tags = [];
store.saveTiddler(tiddlerName,tiddlerName,body,config.options.txtUserName,new Date(),tags);
story.displayTiddler(null,tiddlerName,1);
}
}
createTiddlyButton(place,buttonLabel,buttonLabel,onClick);
}
}
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
"^^1^^The DOCUMENTATION is my guide; I shall not wonder.
^^2^^It maketh me to understand the necessary concepts;
It leadeth me through the installation process.
^^3^^It reassureth me;
It leadeth me on the happy path for my desired objectives.
^^4^^Yea, though I work through the advanced configuration menus,
I will fear no failures, for thou art with me
Thy FAQ and thy troubleshooting they comfort me.
^^5^^Thou providest examples to me in the context of mine use cases.
Thou explainest my expected outcomes.
My results are perfect.
^^6^^Surely good performance and stability will persist throughout the system life
And it will run within the parameters of the DOCUMENTATION forever."
Author: Abi Sutherland at [[Making Light|http://nielsenhayden.com/makinglight/archives/016428.html]]
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactive controls for import/export with filtering.|
Combine tiddlers from any two TiddlyWiki documents. Interactively select and copy tiddlers from another TiddlyWiki source document. Includes prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. When done, a list of all imported tiddlers is written into [[ImportedTiddlers]].
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Revisions
<<<
2011.02.14 4.6.2 fix OSX error: use picker.file.path
2009.10.10 4.6.1 in createImportPanel, Use {{{window.Components}}} instead of {{{config.browser.isGecko}}} to avoid applying FF3 'file browse' fixup in Chrome.
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 6, revision: 2, date: new Date(2011,2,14)};
// 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;
// default shadow definition
config.shadowTiddlers.ImportTiddlers='<<importTiddlers inline>>';
// use shadow tiddler content in backstage panel
if (config.tasks) config.tasks.importTask.content='<<tiddler ImportTiddlers>>' // TW2.2 or above
//}}}
//{{{
// backward-compatiblity for TW2.0.x and TW1.2.x
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={};
if (typeof merge=='undefined') {
function merge(dst,src,preserveExisting) {
for(var i in src) { if(!preserveExisting || dst[i] === undefined) dst[i] = src[i]; }
return dst;
}
}
if (config.browser.isGecko===undefined)
config.browser.isGecko=(config.userAgent.indexOf('gecko')!=-1);
//}}}
//{{{
merge(config.macros.importTiddlers,{
$: function(id) { return document.getElementById(id); }, // abbreviation
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',
filterMsg: "Filtered %0 tiddlers matching '%1'",
summaryMsg: '%0 tiddler%1 in the list',
summaryFilteredMsg: '%0 of %1 tiddler%2 in the list',
plural: 's are',
single: ' is',
countMsg: '%0 tiddlers selected for import',
processedMsg: 'Processed %0 tiddlers',
importedMsg: 'Imported %0 of %1 tiddlers from %2',
loadText: 'please load a document...',
closeText: 'close',
doneText: 'done',
startText: 'import',
stopText: 'stop',
local: true, // default to import from local file
src: '', // path/filename or URL of document to import (retrieved from SiteUrl)
proxy: '', // URL for remote proxy script (retrieved from SiteProxy)
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: 10, // # 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
sync: false, // add 'server' fields to imported tiddlers (for sync function)
lastFilter: '', // most recent filter (URL hash) applied
lastAction: null, // most recent collision button performed
index: 0, // current processing index in import list
sort: '' // sort order for imported tiddler listbox
});
//}}}
//{{{
// hijack core macro handler
if (config.macros.importTiddlers.coreHandler==undefined)
config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.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
createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
} else if (params[0]=='inline') {// show panel as INLINE tiddler content
createImportPanel(place);
this.$('importPanel').style.position='static';
this.$('importPanel').style.display='block';
} else if (config.macros.loadTiddlers)
config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
//{{{
// Handle link click to create/show/hide control panel
function onClickImportMenu(e) { var e=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,false,'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 cmi=config.macros.importTiddlers; // abbrev
var panel=cmi.$('importPanel');
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(store.getTiddlerText('ImportTiddlersPlugin##css'),'importTiddlers');
panel=createTiddlyElement(place,'span','importPanel',null,null)
panel.innerHTML=store.getTiddlerText('ImportTiddlersPlugin##html');
refreshImportList();
if (!cmi.src.length) cmi.src=store.getTiddlerText('SiteUrl')||'';
cmi.$('importSourceURL').value=cmi.src;
if (!cmi.proxy.length) cmi.proxy=store.getTiddlerText('SiteProxy')||'SiteProxy';
cmi.$('importSiteProxy').value=cmi.proxy;
if (window.Components) { // FF3 FIXUP
cmi.$('fileImportSource').style.display='none';
cmi.$('importLocalPanelFix').style.display='block';
}
cmi.$('chkSync').checked=cmi.sync;
cmi.$('chkImportTags').checked=cmi.importTags;
cmi.$('chkKeepTags').checked=cmi.keepTags;
cmi.$('chkAddTags').checked=cmi.addTags;
cmi.$('txtNewTags').value=cmi.newTags;
cmi.$('txtNewTags').style.display=cmi.addTags?'block':'none';
cmi.$('chkSync').checked=cmi.sync;
cmi.$('chkImportReport').checked=config.options.chkImportReport;
return panel;
}
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event) {
var cmi=config.macros.importTiddlers; // abbreviation
var list=cmi.$('importList'); if (!list) return false;
var thePanel=cmi.$('importPanel');
var theCollisionPanel=cmi.$('importCollisionPanel');
var theNewTitle=cmi.$('importNewTitle');
var count=0;
switch (which.id)
{
case 'importFromFile': // show local panel
case 'importFromWeb': // show HTTP panel
cmi.local=(which.id=='importFromFile');
cmi.showPanel('importLocalPanel',cmi.local);
cmi.showPanel('importHTTPPanel',!cmi.local);
break;
case 'importOptions': // show/hide options panel
cmi.showPanel('importOptionsPanel',cmi.$('importOptionsPanel').style.display=='none');
break;
case 'fileImportSource':
case 'importLoad': // load import source into hidden frame
importReport(); // if an import was in progress, generate a report
cmi.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
if (cmi.src=='') break;
// Load document, read it's DOM and fill the list
cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
break;
case 'importSelectFeed': // select a pre-defined systemServer feed URL
var p=Popup.create(which); if (!p) return false;
var tids=store.getTaggedTiddlers('systemServer');
if (!tids.length)
createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
for (var t=0; t<tids.length; t++) {
var u=store.getTiddlerSlice(tids[t].title,'URL');
var d=store.getTiddlerSlice(tids[t].title,'Description');
if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,'description');
if (!d||!d.length) d=u;
createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
function(){
var u=this.getAttribute('url');
document.getElementById('importSourceURL').value=u;
config.macros.importTiddlers.src=u;
document.getElementById('importLoad').onclick();
},
null,null,null,{url:u});
}
Popup.show();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
// create popup with feed list
// onselect, insert feed URL into input field.
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 < list.options.length; t++) {
if (list.options[t].value=='') continue;
list.options[t].selected=true;
count++;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!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 < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value=='') continue;
list.options[t].selected=!store.tiddlerExists(list.options[t].value);
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!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 < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value==''||!store.tiddlerExists(list.options[t].value)) continue;
for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!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 < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value=='') continue;
if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!count;
break;
case 'importApplyFilter': // filter list to include only matching tiddlers
importReport(); // if an import was in progress, generate a report
clearMessage();
if (!cmi.all) // no tiddlers loaded = '0 selected'
{ displayMessage(cmi.countMsg.format([0])); return false; }
var hash=cmi.$('importLastFilter').value;
cmi.inbound=cmi.filterByHash('#'+hash,cmi.all);
refreshImportList(); // reset/resize the listbox
break;
case 'importStart': // initiate the import processing
importReport(); // if an import was in progress, generate a report
cmi.$('importApplyToAll').checked=false;
cmi.$('importStart').value=cmi.stopText;
if (cmi.index>0) cmi.index=-1; // stop processing
else cmi.index=importTiddlers(0); // or begin processing
importStopped();
break;
case 'importClose': // unload imported tiddlers or hide the import control panel
// if imported tiddlers not loaded, close the import control panel
if (!cmi.inbound) { thePanel.style.display='none'; break; }
importReport(); // if an import was in progress, generate a report
cmi.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
break;
case 'importSkip': // don't import the tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
theImported.status='skipped after asking'; // mark item as skipped
theCollisionPanel.style.display='none';
cmi.index=importTiddlers(cmi.index+1); // resume with NEXT item
importStopped();
break;
case 'importRename': // change name of imported tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.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';
cmi.index=importTiddlers(cmi.index); // resume with THIS item
importStopped();
break;
case 'importMerge': // join existing and imported tiddler content
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
var theExisting = store.getTiddler(theItem.value);
var theText = theExisting.text+'\n----\n^^merged from: ';
theText +='[['+cmi.src+'#'+theItem.value+'|'+cmi.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';
cmi.index=importTiddlers(cmi.index); // resume with this item
importStopped();
break;
case 'importReplace': // substitute imported tiddler for existing tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.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';
cmi.index=importTiddlers(cmi.index); // resume with THIS item
importStopped();
break;
case 'importListSmaller': // decrease current listbox size, minimum=5
if (list.options.length==1) break;
list.size-=(list.size>5)?1:0;
cmi.listsize=list.size;
break;
case 'importListLarger': // increase current listbox size, maximum=number of items in list
if (list.options.length==1) break;
list.size+=(list.size<list.options.length)?1:0;
cmi.listsize=list.size;
break;
case 'importListMaximize': // toggle listbox size between current and maximum
if (list.options.length==1) break;
list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
break;
}
}
//}}}
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
if (typeof place=='string') var place=document.getElementById(place);
if (!place||!place.style) return;
if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,'none'));
else place.style.display=show?'block':'none';
}
//}}}
//{{{
function refreshImportList(selectedIndex) {
var cmi=config.macros.importTiddlers; // abbrev
var list=cmi.$('importList'); if (!list) return;
// if nothing to show, reset list content and size
if (!cmi.inbound) {
while (list.length > 0) { list.options[0] = null; }
list.options[0]=new Option(cmi.loadText,'',false,false);
list.size=cmi.listsize;
cmi.$('importLoad').disabled=false;
cmi.$('importLoad').style.display='inline';
cmi.$('importStart').disabled=true;
cmi.$('importOptions').disabled=true;
cmi.$('importOptions').style.display='none';
cmi.$('fileImportSource').disabled=false;
cmi.$('importFromFile').disabled=false;
cmi.$('importFromWeb').disabled=false;
cmi.$('importStart').value=cmi.startText;
cmi.$('importClose').value=cmi.doneText;
cmi.$('importSelectPanel').style.display='none';
cmi.$('importOptionsPanel').style.display='none';
return;
}
// there are inbound tiddlers loaded...
cmi.$('importLoad').disabled=true;
cmi.$('importLoad').style.display='none';
cmi.$('importOptions').style.display='inline';
cmi.$('importOptions').disabled=false;
cmi.$('fileImportSource').disabled=true;
cmi.$('importFromFile').disabled=true;
cmi.$('importFromWeb').disabled=true;
cmi.$('importClose').value=cmi.closeText;
if (cmi.$('importSelectPanel').style.display=='none')
cmi.showPanel('importSelectPanel',true);
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) cmi.sort='title'; // heading
if (selectedIndex==1) cmi.sort='title';
if (selectedIndex==2) cmi.sort='modified';
if (selectedIndex==3) cmi.sort='tags';
if (selectedIndex>3) {
// display selected tiddler count
for (var t=0,count=0; t < list.options.length; t++) {
if (!list.options[t].selected) continue;
if (list.options[t].value!='')
count+=1;
else { // if heading is selected, deselect it, and then select and count all in section
list.options[t].selected=false;
for ( t++; t<list.options.length && list.options[t].value!=''; t++) {
list.options[t].selected=true;
count++;
}
}
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
}
cmi.$('importStart').disabled=!count;
if (selectedIndex>3) return; // no refresh needed
// get the alphasorted list of tiddlers
var tiddlers=cmi.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 (list.length > 0) { list.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
if (cmi.all.length==tiddlers.length)
var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
else
var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
list.options[i++]=new Option(summary,'',false,false);
list.options[i++]=new Option(((cmi.sort=='title' )?'>':indent)+' [by title]','',false,false);
list.options[i++]=new Option(((cmi.sort=='modified')?'>':indent)+' [by date]','',false,false);
list.options[i++]=new Option(((cmi.sort=='tags')?'>':indent)+' [by tags]','',false,false);
// output the tiddler list
switch(cmi.sort) {
case 'title':
for(var t = 0; t < tiddlers.length; t++)
list.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) {
list.options[i++] = new Option(theSection,'',false,false);
lastSection = theSection;
}
list.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];
list.options[i++]=new Option(theTag,'',false,false);
for(var t=0; t<theTitles[theTag].length; t++)
list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
list.selectedIndex=selectedIndex; // select current control item
if (list.size<cmi.listsize) list.size=cmi.listsize;
if (list.size>list.options.length) list.size=list.options.length;
}
//}}}
//{{{
// re-entrant processing for handling import with interactive collision prompting
function importTiddlers(startIndex) {
var cmi=config.macros.importTiddlers; // abbrev
if (!cmi.inbound) return -1;
var list=cmi.$('importList'); if (!list) return;
var t;
// if starting new import, reset import status flags
if (startIndex==0)
for (var t=0;t<cmi.inbound.length;t++)
cmi.inbound[t].status='';
for (var i=startIndex; i<list.options.length; i++) {
// if list item is not selected or is a heading (i.e., has no value), skip it
if ((!list.options[i].selected) || ((t=list.options[i].value)==''))
continue;
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==t) break;
var inbound = cmi.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 (cmi.importTags)
newTags+=inbound.getTags() // import remote tags
if (cmi.keepTags && theExisting)
newTags+=' '+theExisting.getTags(); // keep existing tags
if (cmi.addTags && cmi.newTags.trim().length)
newTags+=' '+cmi.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;
// set sync fields
if (cmi.sync) {
if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
inbound.fields['server.page.revision']=inbound.modified.convertToYYYYMMDDHHMM();
inbound.fields['server.type']='file';
inbound.fields['server.host']=(cmi.local&&!cmi.src.startsWith('file:')?'file:///':'')+cmi.src;
}
// 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 cmi=config.macros.importTiddlers; // abbrev
var list=cmi.$('importList'); if (!list) return;
var theNewTitle=cmi.$('importNewTitle');
if (cmi.index==-1){
cmi.$('importStart').value=cmi.startText;
importReport(); // import finished... generate the report
} else {
// import collision...
// show the collision panel and set the title edit field
cmi.$('importStart').value=cmi.stopText;
cmi.showPanel('importCollisionPanel',true);
theNewTitle.value=list.options[cmi.index].value;
if (cmi.$('importApplyToAll').checked && cmi.lastAction && cmi.lastAction.id!='importRename')
onClickImportButton(cmi.lastAction);
}
}
//}}}
//{{{
function importReport() {
var cmi=config.macros.importTiddlers; // abbrev
if (!cmi.inbound) return;
// if import was not completed, the collision panel will still be open... close it now.
var panel=cmi.$('importCollisionPanel'); if (panel) panel.style.display='none';
// get the alphasorted list of tiddlers
var tiddlers = cmi.inbound;
// gather the statistics
var count=0; var total=0;
for (var t=0; t<tiddlers.length; t++) {
if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
if (tiddlers[t].status.substr(0,7)!='skipped') count++;
total++;
}
// generate a report
if (total) displayMessage(cmi.processedMsg.format([total]));
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[['+cmi.src+'|'+cmi.src+']]:\n';
if (cmi.addTags && cmi.newTags.trim().length)
newText += 'imported tiddlers were tagged with: "'+cmi.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);
story.displayTiddler(null,theReport.title,1,null,null,false);
story.refreshTiddler(theReport.title,1,true);
}
// reset status flags
for (var t=0; t<cmi.inbound.length; t++) cmi.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(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g,' ')]));
}
//}}}
//{{{
// // File and XMLHttpRequest I/O
config.macros.importTiddlers.askForFilename=function(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='';
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.modeOpen);
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.path;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XPSP2 IE 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) { // fallback
var result=prompt(msg,path+file);
}
}
return result;
}
config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
if (src==undefined || !src.length) return null; // filename is required
var original=src; // URL as specified
var hashpos=src.indexOf('#'); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
clearMessage();
displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
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) { // file didn't load, 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);
var txt=loadFile(src);
}
if (!txt) { // file still didn't load, report error
displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g,' '),'(filesystem error)']));
} else {
displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
if (version.major+version.minor*.1+version.revision*.01!=2.52) txt=convertUTF8ToUnicode(txt);
if (callback) callback(true,original,txt,src,null);
}
} else {
doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,original,null);
}
}
config.macros.importTiddlers.readTiddlersFromHTML=function(html){
var remoteStore=new TiddlyWiki();
remoteStore.importTiddlyWiki(html);
return remoteStore.getTiddlers('title');
}
config.macros.importTiddlers.readTiddlersFromCSV=function(CSV){
var remoteStore=new TiddlyWiki();
// GET NAMES
var lines=CSV.replace(/\r/g,'').split('\n');
var names=lines.shift().replace(/"/g,'').split(',');
CSV=lines.join('\n');
// ENCODE commas and newlines within quoted values
var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
CSV=CSV.replace(/"([^"]*?)"/g,
function(x){ return x.replace(/\,/g,comma).replace(/\n/g,newline); });
// PARSE lines
var lines=CSV.split('\n');
for (var i=0; i<lines.length; i++) { if (!lines[i].length) continue;
var values=lines[i].split(',');
// DECODE commas, newlines, and doubled-quotes, and remove enclosing quotes (if any)
for (var v=0; v<values.length; v++)
values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n')
.replace(/^"|"$/g,'').replace(/""/g,'"');
// EXTRACT tiddler values
var title=''; var text=''; var tags=[]; var fields={};
var created=null; var when=new Date(); var who=config.options.txtUserName;
for (var v=0; v<values.length; v++) { var val=values[v];
if (names[v]) switch(names[v].toLowerCase()) {
case 'title': title=val.replace(/\[\]\|/g,'_'); break;
case 'created': created=new Date(val); break;
case 'modified':when=new Date(val); break;
case 'modifier':who=val; break;
case 'text': text=val; break;
case 'tags': tags=val.readBracketedList(); break;
default: fields[names[v].toLowerCase()]=val; break;
}
}
// CREATE tiddler in temporary store
if (title.length)
remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
}
return remoteStore.getTiddlers('title');
}
config.macros.importTiddlers.createTiddlerFromFile=function(src,txt) {
var t=new Tiddler();
var pos=src.lastIndexOf("/"); if (pos==-1) pos=src.lastIndexOf("\\");
t.title=pos==-1?src:src.substr(pos+1);
t.text=txt;
t.created=t.modified=new Date();
t.modifier=config.options.txtUserName;
if (src.substr(src.length-3,3)=='.js') t.tags=['systemConfig'];
return [t];
}
config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr){
var cmi=config.macros.importTiddlers; // abbreviation
var src=src.replace(/%20/g,' ');
if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
cmi.all=cmi.readTiddlersFromHTML(txt);
if (!cmi.all||!cmi.all.length) cmi.all=cmi.readTiddlersFromCSV(txt)
if (!cmi.all||!cmi.all.length) cmi.all=cmi.createTiddlerFromFile(src,txt)
var count=cmi.all?cmi.all.length:0;
var querypos=src.lastIndexOf('?'); if (querypos!=-1) src=src.substr(0,querypos);
displayMessage(cmi.foundMsg.format([count,src]));
cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
cmi.$('importLastFilter').value=cmi.lastFilter;
window.refreshImportList(0);
}
config.macros.importTiddlers.filterByHash=function(src,tiddlers){
var hashpos=src.lastIndexOf('#'); if (hashpos==-1) return tiddlers;
var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
var tids=[];
var params=hash.parseParams('anon',null,true,false,false);
for (var p=1; p<params.length; p++) {
switch (params[p].name) {
case 'anon':
case 'open':
tids.pushUnique(params[p].value);
break;
case 'tag':
if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
} else for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].isTagged(params[p].value))
tids.pushUnique(tiddlers[t].title);
break;
case 'story':
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].title==params[p].value) {
tiddlers[t].changed();
for (var s=0; s<tiddlers[t].links.length; s++)
tids.pushUnique(tiddlers[t].links[s]);
break;
}
break;
case 'search':
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].text.indexOf(params[p].value)!=-1)
tids.pushUnique(tiddlers[t].title);
break;
}
}
var matches=[];
for (var t=0; t<tiddlers.length; t++)
if (tids.contains(tiddlers[t].title))
matches.push(tiddlers[t]);
displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
config.macros.importTiddlers.lastFilter=hash;
return matches;
}
//}}}
/***
!!!Control panel CSS
//{{{
!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;-webkit-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:100%;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 #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;-webkit-border-radius:5px;}
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }
#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:23%; }
#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 }
#backstagePanel #importPanel { left:10%; right:auto; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- source and report -->
<table><tr><td align=left>
import from
<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED
onclick="onClickImportButton(this,event)" title="show file controls"> local file
<input type="radio" class="rad" name="importFrom" id="importFromWeb" value="http"
onclick="onClickImportButton(this,event)" title="show web controls"> web server
</td><td align=right>
<input type=checkbox class="chk" id="chkImportReport"
onClick="config.options['chkImportReport']=this.checked;"> create report
</td></tr></table>
<div class="box" id="importSourcePanel" style="margin:.5em">
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file -->
enter or browse for source 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;document.getElementById('importLoad').onclick()">
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->
<input type="text" id="fileImportSourceFix" style="width:90%"
title="Enter a path/file to import"
onKeyUp="config.macros.importTiddlers.src=this.value"
onChange="config.macros.importTiddlers.src=this.value;document.getElementById('importLoad').onclick()">
<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."
title="Select a path/file to import"
onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;
document.getElementById('fileImportSourceFix').value=r;
config.macros.importTiddlers.src=r;
document.getElementById('importLoad').onclick()">
</div><!--end FF3 FIXUP-->
</div><!--end local-->
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->
<table><tr><td align=left>
enter a URL or <a href="javascript:;" id="importSelectFeed"
onclick="return onClickImportButton(this,event)" title="select a pre-defined 'systemServer' URL">
select a server</a><br>
</td><td align=right>
<input type="checkbox" class="chk" id="importUsePassword"
onClick="config.macros.importTiddlers.usePassword=this.checked;
config.macros.importTiddlers.showPanel('importIDPWPanel',this.checked,true);">password
<input type="checkbox" class="chk" id="importUseProxy"
onClick="config.macros.importTiddlers.useProxy=this.checked;
config.macros.importTiddlers.showPanel('importSiteProxy',this.checked,true);">proxy
</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 id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>
username: <input type=text id="txtImportID" style="width:25%"
onChange="config.options.txtRemoteUsername=this.value;">
password: <input type=password id="txtImportPW" style="width:25%"
onChange="config.options.txtRemotePassword=this.value;">
</div><!--end idpw-->
</div><!--end http-->
</div><!--end source-->
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">
<table><tr><td align=left>
select:
<a href="javascript:;" id="importSelectAll"
onclick="return onClickImportButton(this)" title="SELECT all tiddlers">
all</a>
<a href="javascript:;" id="importSelectNew"
onclick="return onClickImportButton(this)" title="SELECT tiddlers not already in destination document">
added</a>
<a href="javascript:;" id="importSelectChanges"
onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been updated in source document">
changes</a>
<a href="javascript:;" id="importSelectDifferences"
onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been added or are different from existing tiddlers">
differences</a>
</td><td align=right>
<a href="javascript:;" id="importListSmaller"
onclick="return onClickImportButton(this)" title="SHRINK list size">
– </a>
<a href="javascript:;" id="importListLarger"
onclick="return onClickImportButton(this)" title="GROW list size">
+ </a>
<a href="javascript:;" id="importListMaximize"
onclick="return 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>
<div style="text-align:center">
<a href="javascript:;"
title="click for help using filters..."
onclick="alert('A filter consists of one or more space-separated combinations of: tiddlertitle, tag:[[tagvalue]], tag:[[tag expression]] (requires MatchTagsPlugin), story:[[TiddlerName]], and/or search:[[searchtext]]. Use a blank filter to restore the list of all tiddlers.'); return false;"
>filter</a>
<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"
title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."
onfocus="this.select()" value=""
onKeyUp="config.macros.importTiddlers.lastFilter=this.value"
onChange="config.macros.importTiddlers.lastFilter=this.value;">
<input type="button" id="importApplyFilter" style="width:20%" value="apply"
title="filter list of tiddlers to include only those that match certain criteria"
onclick="return onClickImportButton(this)">
</div>
</div><!--end select-->
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">
apply tags: <input type=checkbox class="chk" id="chkImportTags" checked
onClick="config.macros.importTiddlers.importTags=this.checked;">from source
<input type=checkbox class="chk" id="chkKeepTags" checked
onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing
<input type=checkbox class="chk" id="chkAddTags"
onClick="config.macros.importTiddlers.addTags=this.checked;
config.macros.importTiddlers.showPanel('txtNewTags',this.checked,false);
if (this.checked) document.getElementById('txtNewTags').focus();">add tags<br>
<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15 onfocus="this.select()"
title="enter tags to be added to imported tiddlers"
onKeyUp="config.macros.importTiddlers.newTags=this.value;
document.getElementById('chkAddTags').checked=this.value.length>0;" autocomplete=off>
<nobr><input type=checkbox class="chk" id="chkSync"
onClick="config.macros.importTiddlers.sync=this.checked;">
link tiddlers to source document (for sync later)</nobr>
</div><!--end options-->
<div id="importButtonPanel" style="text-align:center">
<input type=button id="importLoad" class="importButton btn3" value="open"
title="load listbox with tiddlers from source document"
onclick="onClickImportButton(this)">
<input type=button id="importOptions" class="importButton btn3" value="options..."
title="set options for tags, sync, etc."
onclick="onClickImportButton(this)">
<input type=button id="importStart" class="importButton btn3" value="import"
title="start/stop import of selected source tiddlers into current document"
onclick="onClickImportButton(this)">
<input type=button id="importClose" class="importButton btn3" value="done"
title="clear listbox or hide control panel"
onclick="onClickImportButton(this)">
</div>
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">
<table><tr><td style="width:65%" align="left">
<table><tr><td align=left>
tiddler already exists:
</td><td align=right>
<input type=checkbox class="chk" id="importApplyToAll"
onclick="document.getElementById('importRename').disabled=this.checked;"
checked>apply to all
</td></tr></table>
<input type=text id="importNewTitle" size=15 autocomplete=off">
</td><td style="width:34%" align="center">
<input type=button id="importMerge"
class="importButton" style="width:47%" value="merge"
title="append the incoming tiddler to the existing tiddler"
onclick="onClickImportButton(this)"><!--
--><input type=button id="importSkip"
class="importButton" style="width:47%" value="skip"
title="do not import this tiddler"
onclick="onClickImportButton(this)"><!--
--><br><input type=button id="importRename"
class="importButton" style="width:47%" value="rename"
title="rename the incoming tiddler"
onclick="onClickImportButton(this)"><!--
--><input type=button id="importReplace"
class="importButton" style="width:47%" value="replace"
title="discard the existing tiddler"
onclick="onClickImportButton(this)">
</td></tr></table>
</div><!--end collision-->
!end
//}}}
***/
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for ImportTiddlersPlugin|
Combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a source document and import selected tiddlers, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. 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>>
Enter a document URL or press "..." to select a TiddlyWiki file to import, and then press ''[open]''. //Note: There may be a delay before the list of tiddlers appears.// Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time.
Select one or more titles from the listbox. Use CTRL-click or SHIFT-click to select/deselect individual titles. Click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list, based on a comparison of the two documents:
*''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)
Press ''[import]'' to begin copying tiddlers to the current document. If an 'inbound' tiddler matches one that already exists in the document, 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 the tiddler, press ''skip''
* to give the inbound tiddler a different name, so that both the old and new tiddlers will exist when the import is done, enter a new title in the input field and press ''rename''
* to combine the content from both tiddlers into a single tiddler so you can then edit it later to eliminate unwanted content, press ''merge''
* to overwrite the existing tiddler with the imported one (discarding the previous content), press ''[replace]''
''Import Report History''
Whenever tiddlers are imported, a report is generated into a tiddler named [[ImportedTiddlers]], recording when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom, as well as a list of the tiddlers that were processed. When more tiddlers are imported at a later time, a new report is //added// to the existing [[ImportedTiddlers]], above the previous report (i.e., at the top of the tiddler), so that a history of imports is maintained. If this record is not desired, you can delete [[ImportedTiddlers]] at any time.
Note: You can prevent a report from being generated for any given import activity by clearing the "create a report" checkbox before pressing the ''import'' button
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, support for TW2.1.x and earlier have been moved to [[ImportTiddlersPluginPatch]]. ''//Only install the patch plugin when using TW2.1.x or earlier.//''
<<<
!!!!!Revisions
<<<
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
2009.09.27 4.5.5 in readTiddlersFromCSV(), strip \r from input and fixed handling for quoted values
2009.09.12 4.5.4 fixed 'return false' to prevent IE page transition. Also, moved html/css definitions to separate sections
2009.08.23 4.5.3 in importTiddlers(), add 'file:///' to local server.host sync field only if not already present in URL
2009.08.20 4.5.2 only use SiteURL/SiteProxy values if control panel value has not yet been set
2009.07.03 4.5.1 fixups for TW252: doHttp() doesn't return XHR and convertUTF8ToUnicode() not needed for local I/O
2009.05.04 4.5.0 import from CSV-formatted files
2009.03.04 4.4.2 in createImportPanel(), init option checkboxes so display matches internal state variables
2009.02.26 4.4.1 use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.30 4.4.0 added fallback definition of merge() for use with TW2.0.x and TW1.2.x
2008.08.12 4.3.3 rewrite backstage and shadow tiddler definitions for easier customization
2008.08.05 4.3.2 rewrote loadRemoteFile() to eliminate use of platform-specific fileExists() function
2008.06.29 4.3.1 More layout/animation work for simpler sequential interaction. Code reduction/cleanup
2008.06.28 4.3.0 HTML and CSS cleanup and tweaks to layout. Added animation to panels
2008.06.22 4.2.0 For FireFox, use HTML with separate text+button control instead of type='file' control
2008.06.05 4.1.0 in filterByHash(), added support for boolean tag expressions using getMatchingTiddlers() (defined by MatchTagsPlugin)
2008.05.12 4.0.2 automatically tweak the backstage "import" task to add the ImportTiddlers control panel
2008.04.30 4.0.1 trim #... suffix for loading files/URLs in IE
2008.04.30 4.0.0 added source filtering (using URL paramifiers). Also, abbreviations for code-size reduction.
2008.04.13 3.9.0 added 'apply to all' checkbox for collision processing
2008.03.26 3.8.0 added support for selecting pre-defined systemServer URLs
2008.03.25 3.7.0 added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
2008.01.03 3.6.0 in loadRemoteFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.10.30 3.5.6 update [[ImportTiddlers]] shadow tiddler definition to include "inline" link
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 TW2.1.x to [[ImportTiddlersPluginPatch2.1.x]].
2007.06.25 3.5.4 added calls to store.suspendNotifications() and store.resumeNotifications(). Eliminates redisplay processing overhead DURING import activities
2007.04.29 3.5.3 in refreshImportList() when inbound tiddlers are loaded, change "close" button to "done", and disable certain controls to creates a modal condition, so that actions that reload tiddlers cannot be performed unless "done" is first pressed to end the mode..
2007.04.28 3.5.2 in handler(), added param support for custom link label/prompt
2007.04.19 3.5.1 in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content. Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.03.22 3.5.0 in refreshImportList(), add handling for 'select section' when a heading is selected. Makes it really easy to import by tag or date!
2007.03.21 3.4.0 split loadTiddlers functionality into separate plugin (see [[LoadTiddlersPlugin]])
2007.03.20 3.3.1 tweak to previous change to allow relative file references via http: (bypasses getLocalPath() so remote URL will be used)
2007.03.20 3.3.0 added support for local, relative file references: in loadRemoteFile(), check for fileExists(). If not found, prepend relative path and retry.
2007.02.24 3.2.1 re-labeled control panel "open" button to "load"
2007.02.09 3.2.0 loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)
2007.02.08 3.1.3 loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)
2006.11.14 3.1.2 fix macro handler parameter declaration (double-pasted param list corrupts IE)
2006.11.13 3.1.1 use apply() method to invoke hijacked core handler
2006.11.13 3.1.0 hijack built-in importTiddlers.handler() to co-exist with plugin interface. If no params or 'core' keyword, display core interface. "link" param embeds "import tiddlers" link that shows floating panel when clicked.
2006.10.12 3.0.8 in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)
2006.09.10 3.0.7 in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body"
2006.08.16 3.0.6 Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with adaptations that hijack low-level tiddler handling. in CreateImportPanel(), removed "refresh listbox after every tiddler change".
2006.07.29 3.0.5 added noChangeMsg to loadTiddlers processing. if not 'quiet' mode, reports skipped tiddlers.
2006.04.18 3.0.4 in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)
2006.04.12 3.0.3 moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.
2006.04.12 3.0.2 more work on 'core candidate' code. Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.
2006.04.04 3.0.1 in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section
2006.04.04 3.0.0 Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Removed support for "importReplace/importPublic" tags and "force" param (unused feature).
2006.03.30 2.9.1 when extracting store area from remote URL, look for "</body>" instead of "</body>\n</html>" so it will match even if the "\n" is absent from the source.
2006.03.30 2.9.0 added optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.
2006.03.28 2.8.1 in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (not in IE). Also, when extracting store area, look for "</body>\n</html>" and omit extra content that may have been added to the end of the file.
2006.02.21 2.8.0 added support for "tiddler:TiddlerName" filtering parameter in auto-import processing
2006.02.21 2.7.1 Clean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)
2006.02.21 2.7.0 Added "local file" and "web server" radio buttons. Default remote URL uses value from [[SiteURL]]. Also, added 'proxy' option, using value from [[SiteProxy]] as prefix to permit cross-domain document access via server-side scripting.
2006.02.17 2.6.0 Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. fixed init of "add new tags" checkbox
2006.02.16 2.5.4 added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.
2006.02.14 2.5.3 FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()
2006.02.10 2.5.2 corrected unintended global variable in importReport().
2006.02.05 2.5.1 moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals
2006.01.18 2.5.0 added checkbox for "create a report". Default is to create/update the ImportedTiddlers report.
2006.01.15 2.4.1 added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic
2006.01.15 2.4.0 Added support for tagging tiddlers with importSkip, importReplace, and/or importPrivate to enable/disable overwriting or sharing with others when using auto-import macro syntax. Defaults: don't overwrite existing tiddlers, and allow your tiddlers to be auto-imported by others.
2006.01.15 2.3.2 Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)
2006.01.15 2.3.1 Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME to prevent imported document's core code from being invoked. Also, when importing local documents, use convertUTF8ToUnicode() to support international characters sets.
2006.01.12 2.3.0 Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest instead of waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' mode, using macro parameters to specify source path/file or URL, and select tiddlers to import. Improved messages and added optional 'quiet' switch for batch mode to eliminate //most// feedback.
2006.01.11 2.2.0 Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
2006.01.08 2.1.0 IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.
2006.01.06 2.0.2 When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.
2006.01.04 2.0.1 When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.
2005.12.27 2.0.0 Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
2005.12.22 1.3.1 tweak formatting in importReport() and add 'discard report' link to output
2005.12.03 1.3.0 Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)
2005.11.29 1.2.1 fixed formatting of 'detail info' in importReport()
2005.11.11 1.2.0 added 'inline' param to embed controls in a tiddler
2005.11.09 1.1.0 only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.
2005.10.25 1.0.5 fixed typo in importReport() that prevented reports from being generated
2005.10.09 1.0.4 combined documentation with plugin code instead of using separate tiddlers
2005.08.05 1.0.3 moved CSS and HTML definitions into plugin code instead of using separate tiddlers
2005.07.27 1.0.2 core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()
2005.07.23 1.0.1 added parameter checks and corrected addNotification() usage
2005.07.20 1.0.0 Initial Release
<<<
On Sunday, October 06, 2013 6:24:42 AM, J. K. Hoffman imported 7 tiddlers from
[[QuartetWorldsWiki.html|QuartetWorldsWiki.html]]:
<<<
#[[InfoBoxPlugin]] - added
#[[cautionInfoBox]] - added
#[[disputedInfoBox]] - added
#[[icons]] - added
#[[stubInfoBox]] - added
#[[tipInfoBox]] - added
#[[warningInfoBox]] - added
<<<
/***
|Name|InfoBoxPlugin|
|Description||
|Source||
|Documentation||
|Version|0.1|
|Author|Michael Mahemoff, Osmosoft|
|''License:''|[[BSD open source license]]|
|~CoreVersion|2.2|
***/
/*{{{*/
(function() {
if(version.extensions.InfoBoxPlugin) return;
var plugin = version.extensions.InfoBoxPlugin = {installed:true};
var $=jQuery;
applyStyleSheet();
var macro = config.macros.infoBox = {
//================================================================================
// MACRO INITIALISATION
//================================================================================
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var boxEl = $("<div class='infoBox'/>")
.css("marginRight", $(place).parents(".tiddler").find(".tagged").width()+30)
.appendTo(place);
var type = trim(paramString);
if (!trim(type).length) {
wikifier.subWikify(boxEl.get(0), ">>");
return;
}
var headingEl = $("<h3/>").html(type).appendTo(boxEl);
var messageEl = $("<div/>").appendTo(boxEl);
$(wikifier.subWikify(messageEl.get(0), ">>"));
var typeDefinitionTiddler = store.getTiddler(type+"InfoBox");
if (!typeDefinitionTiddler) return;
updateCSS(boxEl, "background", type, "background");
updateCSS(boxEl, "borderColor", type, "borderColor");
updateCSS(headingEl, "color", type, "headingColor");
if (getSlice(type, "heading")) headingEl.html(getSlice(type, "heading"));
updateCSS(messageEl, "color", type, "messageColor");
updateCSS(messageEl, "fontStyle", type, "messageFontStyle");
if (getSlice(type, "message")) messageEl.html(getSlice(type, "message"));
var NORMAL_PADDING=parseInt(trim(store.getTiddlerText("InfoBoxPlugin::Padding")));
if (getSlice(type, "iconURL")) {
var iconURL = getSlice(type, "iconURL");
boxEl.addClass("infoBoxIconed");
boxEl.css({
backgroundImage: "url('"+iconURL+"')",
backgroundPosition: "5px center",
backgroundRepeat: "no-repeat",
});
var leftPadding = (getSlice(type, "iconWidth")) ? (parseInt(getSlice(type, "iconWidth"))||40)+10 : 0;
if (leftPadding) {
boxEl.css({
paddingLeft: leftPadding,
width: usingIEBoxModel() ? 400 : 400-leftPadding+NORMAL_PADDING
});
}
}
}
};
function updateCSS(el, property, infoBoxType, sliceName) {
var sliceValue = store.getTiddlerSlice(infoBoxType+"InfoBox", sliceName);
if (sliceValue) el.css(property, sliceValue);
}
function getSlice(infoBoxType, property) {
var value = wikifyStatic(store.getTiddlerSlice(infoBoxType+"InfoBox", property));
var processed = store.getTiddlerText(value);
return processed ? trim(processed) : value; // if !getTiddlerText, we assume its a URL
}
//################################################################################
//# UTILITIES
//################################################################################
function usingIEBoxModel() {
return config.browser.isIE && !(/Trident/.test(navigator.userAgent));
}
function applyStyleSheet() {
var stylesheet = store.getTiddlerText(tiddler.title + "##StyleSheet");
config.shadowTiddlers["StyleSheetInfoBoxPlugin"] = stylesheet;
store.addNotification("StyleSheetInfoBoxPlugin", refreshStyles);
}
function trim(s) { return s.replace(/^[ \n\t]*/, "").replace(/[ \n\t]*$/g, ""); }
function log() {
if (console && console.log) console.log.apply(console, arguments);
}
//################################################################################
//# CUSTOM STYLESHEET
//################################################################################
/***
!StyleSheet
div.infoBox { border: 1px solid [[ColorPalette::SecondaryDark]];
background-color: [[ColorPalette::SecondaryPale]];
padding: [[InfoBoxPlugin::Padding]]px; margin: 0; width: 400px; }
div.infoBox h3 { border-bottom: 0; margin-top: 0; color: [[ColorPalette::PrimaryDark]]; }
div.infoBox .message { font-style: italic; }
!(end of StyleSheet)
|Padding|5|
!(end of padding)
***/
})();
/*}}}*/
/***
|Name|[[InfoboxTablesPlugin]]|
|Source|http://infoboxes.tiddlyspot.com|
|Documentation|[[InfoboxTablesPluginInfo]]|
|Version|2.2.2|
|Author|Kristjan Brezovnik|
|License|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|~CoreVersion|2.6.3|
|Requires||
|Type|plugin|
|Description|Provides customizable infoboxes for different types of articles.|
!Configuration
<<option chkHideInfoboxes>> Hide the infoboxes when opening a tiddler
<<option chkSaveMode>> When editing the table, save the macro so each parameter is in its own line (default) or so that the entire macro is a single line
<<option chkSavePrompt>> Prompt if you really want to save
!Code
***/
//{{{
//Ensure that the plugin is only installed once
if (!version.extensions.InfoboxTablesPlugin) {
version.extensions.InfoboxTablesPlugin = {installed: true};
version.extensions.InfoboxTablesPlugin = {major: 2, minor: 2, revision: 1, date: new Date(2013,4,22)};
//}}}
/***
!!Generic Color Palette
***/
//{{{
var palette = store.getTiddler("InfoboxTablesColorPalette");
if (palette === null) {
config.shadowTiddlers.InfoboxTablesColorPalette =
"/***\nGeneric Color Palette\n***/\n/*{{{*/\n" +
"InfoboxTableBackground: whitesmoke\n" +
"InfoboxTableTopColor: whitesmoke\n" +
"InfoboxTypeError: red\n" +
"/*}}}*/\n/***\nTemplate-Specific Color Palette\n***/\n/*{{{*/\n";
}
//}}}
/***
!!Generic Stylesheet
***/
//{{{
var stylesheet = store.getTiddler("InfoboxTablesStylesheet");
if (stylesheet === null) {
config.shadowTiddlers.InfoboxTablesStylesheet =
"/***\nGeneric Stylesheet\n***/\n/*{{{*/\n" +
".InfoboxTable {width: 300px !important; margin: 0px 1px !important; border-collapse: separate !important; border: none 0px !important; border-spacing: 0px !important;}\n" +
".InfoboxTableHeader, .InfoboxTableFooter {width: 300px !important; font-size: 10px; font-weight: bold; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n" +
".InfoboxTableHeader {border-radius: 10px 10px 0px 0px; -moz-border-radius: 10px 10px 0px 0px; -webkit-border-radius: 10px 10px 0px 0px;} /* Header table */\n" +
".InfoboxTableFooter {border-radius: 0px 0px 10px 10px; -moz-border-radius: 0px 0px 10px 10px; -webkit-border-radius: 0px 0px 10px 10px;} /* Footer table */\n" +
".InfoboxTableTop, .InfoboxTableBottom {width: 300px !important; border: none 0px; text-align: center; font-size: 16px; line-height: 120%;}\n" +
".InfoboxTableTop {font-size: 14px; line-height: 120%; border-radius: 10px 10px 0px 0px; -moz-border-radius: 10px 10px 0px 0px; -webkit-border-radius: 10px 10px 0px 0px;} /* Header row */\n" +
".InfoboxTableBottom {line-height: 80%; border-radius: 0px 0px 10px 10px; -moz-border-radius: 0px 0px 10px 10px; -webkit-border-radius: 0px 0px 10px 10px;} /* Footer row */\n" +
".InfoboxSection {width: 300px !important; border: none 0px; font-weight: bold;} /* Section header row */\n" +
".InfoboxRow {display: table-row;} /* Content row */\n" +
".InfoboxCellLeft, .InfoboxCellRight, .InfoboxCellEqual, .InfoboxCellImage {border: 1px solid; vertical-align: top !important; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]; word-wrap: break-word !important; word-break: hyphenate !important;}\n" +
".InfoboxCellLeft {width: 100px !important; max-width: 90px !important;}\n" +
".InfoboxCellRight {width: 200px !important; max-width: 190px !important;}\n" +
".InfoboxCellEqual {width: 150px !important; max-width: 140px !important;}\n" +
".InfoboxCellImage, .InfoboxCellSingle {width: 300px !important;}\n" +
".InfoboxCellImage {text-align: center;}\n" +
".InfoboxCellSingle {text-align: left;}\n" +
"img.InfoboxImage {max-width: 290px !important;} /* Image max width must be less than cell width */\n" +
".InfoboxOuterDiv, .InfoboxInnerDiv {display: block; position: relative; float: right; clear: both;}\n" +
".SmallButton {display: inline; position: relative; float: right;}\n" +
".InfoboxOuterDiv {z-index: 10; padding: 0.5em; margin: 0px;}\n" +
".InfoboxOuterDivCommand, .InfoboxInnerDivCommand {display: inline-block; position: relative; clear: both;}\n" +
".SmallButton {border: 1px solid black!important; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]!important; padding: 1px; margin: 1px;}\n" +
".SmallButton, .SmallText,.InfoboxCellLeft, .InfoboxCellRight, .InfoboxCellEqual, .InfoboxCellImage, .InfoboxSection {font-size: 10px; line-height: 120%;}\n" +
".InfoboxNoInfo {display: none; width: 300px !important; font-weight: bold; border: solid 2px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;} /* No Info */\n" +
".InfoboxError {width: 300px !important; font-weight: bold; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px; float: right;} /* Error */\n" +
".InfoboxTypeError {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px; float: right;} /* Type Error */\n" +
".TypeErrorEditMode {background: [[InfoboxTablesColorPalette::InfoboxTypeError]];}\n" +
".InfoboxEditTextarea {height: 20px; width: 99% !important; border: 1px solid black !important; padding: 0px !important; margin: 0px !important; overflow: auto; overflow-y: scroll !important; resize: vertical !important;} /* Textarea on the edit panel*/\n" +
".InfoboxEditTextareaOnfocus {height: 200px; width: 97% !important;}\n" +
".InfoboxEditTextareaOnblur {height: 16px; width: 97% !important;}\n" +
".EqualEditParamName {display: none;}\n" +
".EditComment {display: none;}\n" +
"/*}}}*/\n/***\nTemplate-Specific Stylesheet\n***/\n/*{{{*/\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
}
//}}}
/***
!!Template-Specific Color Palette, Stylesheet
***/
//{{{
var list = store.getTaggedTiddlers("infobox");
var listTitle, listColors, listColorsText, listColorsTitle, listColorsSubtitle, paramListInfo, paramListInfoParsed;
var i, j;
var validTypes = "";
for (i = 0; i < list.length; i++) {
listTitle = list[i].title.replace(/Infobox|_| /g, "");
validTypes += list[i].title.replace(/Infobox_/, "").replace(/_/g, " ") + ", ";
listColorsText = store.getTiddlerText(list[i].title + "::Text");
listColorsTitle = store.getTiddlerText(list[i].title + "::Title");
listColorsSubtitle = store.getTiddlerText(list[i].title + "::Subtitle");
if (listColorsText === null) {
listColorsText = "black";
}
if (listColorsTitle === null) {
listColorsTitle = "white";
}
if (listColorsSubtitle === null) {
listColorsSubtitle = "white";
}
//Color Palette
if (palette === null) {
config.shadowTiddlers.InfoboxTablesColorPalette +=
"Infobox" + listTitle + "Text: " + listColorsText + "\n" +
"Infobox" + listTitle + "Title: " + listColorsTitle + "\n" +
"Infobox" + listTitle + "Subtitle: " + listColorsSubtitle + "\n";
}
//Stylesheet
if (stylesheet === null) {
config.shadowTiddlers.InfoboxTablesStylesheet +=
".Infobox" + listTitle + "Title {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; color: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Text]];}\n" +
".Infobox" + listTitle + "Subtitle {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Subtitle]]; color: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Text]];}\n" +
".NoInfo" + listTitle + " {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; color: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Text]];}\n" +
".Infobox" + listTitle + "Error {background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; color: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Text]]; border: solid 5px [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]];}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
}
}
if (palette === null) {
config.shadowTiddlers.InfoboxTablesColorPalette += "/*}}}*/\n";
}
if (stylesheet === null) {
config.shadowTiddlers.InfoboxTablesStylesheet += "/*}}}*/\n";
}
//}}}
/***
!!Infobox Macro
***/
//{{{
config.macros.infobox = {};
config.macros.infobox.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
params = paramString.parseParams(null, null, true);
var Type = getParam(params, 'Type', 'unknown');
var Title = getParam(params, 'Title', tiddler.title);
var InstanceID = getParam(params, 'InstanceID', 'DefaultID');
var TypeX = Type.replace(/[\s]/g, "");
var TitleX = Title.replace(/[\W\s]/g, "");
var InstanceIDX = InstanceID.replace(/[\W\s]/g, "");
var TTIX = TypeX + TitleX + InstanceIDX;
//Decide if the infoboxes should be displayed by default or not
if (config.options.chkHideInfoboxes === undefined) {
config.options.chkHideInfoboxes = false;
}
if (config.options.chkSaveMode === undefined) {
config.options.chkSaveMode = true;
}
if (config.options.chkSavePrompt === undefined) {
config.options.chkSavePrompt = true;
}
var noEdit = "false";
//Create the outer container
var infoboxDiv = createTiddlyElement(place, "div", "InfoboxOuterDiv"+TTIX, "InfoboxOuterDiv");
var saveButton, editButton, deleteButton, toggleButton, infoboxTableDiv, infoboxTableEditDiv;
//Set initial values for the toggle button
var closedtext = "show";
var closedtip = "show";
var openedtext = "hide";
var openedtip = "hide";
var toggleButtonTitle, toggleButtonTooltip;
var hideInfoboxes = config.options.chkHideInfoboxes;
if (hideInfoboxes === true) {
toggleButtonTitle = (hideInfoboxes === true ? closedtext : openedtext);
toggleButtonTooltip = (hideInfoboxes === true ? closedtip : openedtip);
}
else {
toggleButtonTitle = (hideInfoboxes === false ? openedtext : closedtext);
toggleButtonTooltip = (hideInfoboxes === false ? openedtip : closedtip);
}
//Create the toggle button
toggleButton = createTiddlyButton(infoboxDiv, toggleButtonTitle, toggleButtonTooltip, function() {config.macros.infobox.toggleInfobox(editButton,toggleButton,infoboxTableDiv);}, "SmallButton", "SmallButton"+TTIX);
toggleButton.style.display = "block";
toggleButton.setAttribute("closedtext",closedtext);
toggleButton.setAttribute("closedtip",closedtip);
toggleButton.setAttribute("openedtext",openedtext);
toggleButton.setAttribute("openedtip",openedtip);
//Create the delete button
deleteButton = createTiddlyButton(infoboxDiv, "delete", "delete infobox", function() {config.macros.infobox.deleteInfobox(Type,Title,InstanceID);}, "SmallButton", "SmallButtonSave"+TTIX);
deleteButton.style.display = "none";
//Set initial values for the edit/cancel button
var edittext = "edit";
var edittip = "edit infobox";
var canceltext = "cancel";
var canceltip = "cancel edit";
//Create the edit/cancel button
editButton = createTiddlyButton(infoboxDiv, "edit", "edit infobox", function() {config.macros.infobox.editInfobox(saveButton,editButton,deleteButton,toggleButton,infoboxTableDiv,infoboxTableEditDiv,Title,noEdit);}, "SmallButton", "SmallButtonEdit"+TTIX);
if (hideInfoboxes === true) {
editButton.style.display = "none";
}
else {
editButton.style.display = "block";
}
editButton.setAttribute("edittext",edittext);
editButton.setAttribute("edittip",edittip);
editButton.setAttribute("canceltext",canceltext);
editButton.setAttribute("canceltip",canceltip);
//Create the save button
saveButton = createTiddlyButton(infoboxDiv, "save", "save infobox", function() {config.macros.infobox.saveInfobox(saveButton,editButton,deleteButton,toggleButton,infoboxTableDiv,infoboxTableEditDiv,Type,Title,InstanceID);}, "SmallButton", "SmallButtonSave"+TTIX);
saveButton.style.display = "none";
//Create the container for the table
infoboxTableDiv = createTiddlyElement(infoboxDiv, "div", "InfoboxInnerDiv"+TTIX, "InfoboxInnerDiv");
if (hideInfoboxes === true) {
infoboxTableDiv.style.display = "none";
}
else {
infoboxTableDiv.style.display = "block";
}
//Create container for the edit table
infoboxTableEditDiv = createTiddlyElement(infoboxDiv, "div", "InfoboxEditInnerDiv"+TTIX, "InfoboxInnerDiv");
infoboxTableEditDiv.style.display = "none";
//Cancel edit by pressing escape
infoboxDiv.onkeyup = function(e) {
if (e.keyCode === 27) {
config.macros.infobox.editInfobox(saveButton,editButton,deleteButton,toggleButton,infoboxTableDiv,infoboxTableEditDiv,Title,noEdit);
}
};
//Output for beginning of table
var start = "<html><div id=\"DivContainer" + TTIX + "\"><table id=\"Header" + TTIX + "\" class=\"InfoboxTable InfoboxTableHeader\"><tr id=\"Title" + TTIX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"2\">" + Title + "</td></tr>";
//Output for content of table
var out = "";
//Output for end of table
var end = "</table><table id=\"Footer" + TTIX + "\" class=\"InfoboxTable InfoboxTableFooter\"><tr id=\"Info" + TTIX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\"> </td></tr></table></div><div id=\"NoInfo" + TTIX + "\" class=\"InfoboxNoInfo NoInfo" + TypeX + "\">No information available.</div></html>{{SmallButton{[[View template|Infobox_" + Type.replace(/ /g, "_") + "]]}}}";
//Output for beginning of edit table
var startEdit = "<html><div id=\"EditDivContainer" + TTIX + "\"><table id=\"EditHeader" + TTIX + "\" class=\"InfoboxTable\"><tr><td class=\"InfoboxSection Infobox" + TypeX + "Subtitle\" colspan=\"2\">Infobox Head</td></tr><tr id=\"EditType" + TTIX + "\"><td class=\"InfoboxCellLeft\">Type</td><td class=\"InfoboxCellRight\">" + Type + "</td></tr><tr id=\"EditTitle" + TTIX + "\"><td class=\"InfoboxCellLeft\">Title</td><td class=\"InfoboxCellRight\"><textarea id=\"EditTextareaTitle" + TTIX + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value;\">" + Title + "</textarea></td></tr><tr id=\"EditInstanceID" + TTIX + "\"><td class=\"InfoboxCellLeft\">Instance ID</td><td class=\"InfoboxCellRight\"><textarea id=\"EditTextareaInstanceID" + TTIX + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value;\">" + InstanceID + "</textarea></td></tr><tr><td class=\"InfoboxSection Infobox" + TypeX + "Subtitle\" colspan=\"2\">Infobox Content</td></tr>";
//Output for content of edit table
var outEdit = "";
//Output for end of edit table
var endEdit = "</table></div></html>";
//If Type is missing
if (Type === "unknown" || Type === null || Type.length === 0) {
wikify("{{InfoboxTypeError{\nType is mandatory! Allowed types are: " + validTypes.replace(/, $/, "") + "\nEdit mode is not available.}}}", infoboxTableDiv);
noEdit = "true";
return;
}
//If Type is wrong
else if (validTypes.indexOf(Type) === -1) {
wikify("{{InfoboxTypeError{\nYou entered a non-existent type! Allowed types are: " + validTypes.replace(/, $/, "") + "\nEdit mode is not available.}}}", infoboxTableDiv);
noEdit = "true";
return;
}
//If Type is okay
else if (validTypes.indexOf(Type) !== -1) {
//Check how many instances of the same type there are in a tiddler
var instanceCheck = store.getTiddlerText(tiddler.title);
var instanceInfobox = instanceCheck.match(/<<infobox/g); //Find all instances of the macro in the tiddler
if (instanceInfobox.length > 1) { //If there is more than one instance
var instanceInfoboxType = instanceCheck.match(/<<infobox[\w\W\s]*?Type:"[\w\s]*?"[\w\W\s]*?>>/g); //Get all infoboxes
var instanceInfoboxTypeResultEmpty = [];
var instanceInfoboxTypeResult = [];
var l;
for (l = 0; l < instanceInfoboxType.length; l++) {
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && (InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf("\""+Type+"\"") !== -1)) { //If the infobox matches the type and does not have an InstanceID parameter, put it into array
instanceInfoboxTypeResultEmpty.push(instanceInfoboxType[l]);
}
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && !(InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf("\""+Type+"\"") !== -1)) { //If the infobox matches the type and has an InstanceID parameter, put it into array
instanceInfoboxTypeResult.push(instanceInfoboxType[l]);
}
}
if (instanceInfoboxTypeResultEmpty.length > 1) { //If there is more than one infobox without the InstanceID parameter
var instanceIDCount = 0;
var m;
for (m = 0; m < instanceInfoboxTypeResultEmpty.length; m++) { //Count the number or missing InstanceID parameters
if (instanceInfoboxTypeResultEmpty[m].match(/InstanceID:"[\w\s]*?"/g) !== null) {
instanceIDCount = instanceIDCount + 1;
}
}
if (instanceInfoboxType.length > instanceIDCount) { //If there are more infoboxes than InstanceID parameters per type
if (InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) { //Display error message for all infoboxes without an InstanceID parameter
wikify("{{InfoboxError Infobox" + TypeX + "Error{\nThere are ''" + instanceInfoboxTypeResultEmpty.length + "'' infoboxes of ''\"" + Type + "\"'' type, but ''" + instanceIDCount + "'' ~IDs. This infobox does not have an ''~InstanceID'' parameter.<br/>When using more than one infobox of the same type, you need to add ''~InstanceID'' parameter to all of them. This parameter can be a random ''alphanumeric'' string and must be different for each infobox of the same type.\nEdit mode is not available.}}}", infoboxTableDiv);
noEdit = "true";
return;
}
}
} //End missing instanceID check
//Check for duplicate InstanceID parameters for a type
var instanceIDs = [];
var instanceIDMatch;
var n;
if (instanceInfoboxTypeResult.length > 1) { //If there is more than one infobox with the InstanceID parameter
for (n = 0; n < instanceInfoboxTypeResult.length; n++) { //Count the number or InstanceID parameters
if ((instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g) !== null) && !(InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0)) {
instanceIDMatch = instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g);
instanceIDs.push(instanceIDMatch);
}
}
var instanceIDsSorted = instanceIDs.sort();
var duplicateIDs = [];
var o;
for (o = 0; o < instanceIDsSorted.length - 1; o++) { //Find the duplicates
if (instanceIDsSorted[o].toString() === instanceIDsSorted[o+1].toString()) {
duplicateIDs.push(instanceIDsSorted[o]);
}
}
if (duplicateIDs.length > 0) {
wikify("{{InfoboxError Infobox" + TypeX + "Error{\nThis infobox has the same ''~InstanceID'' parameter (''\"" + InstanceID + "\"'') as another infobox of the same type (''\"" + Type + "\"'').<br/>Infoboxes of the same type must have ''unique ~IDs''.\nEdit mode is not available.}}}", infoboxTableDiv);
noEdit = "true";
return;
}
} //End duplicate check
} //End of checks when there's more than one instance
//Begin parsing parameters for output
noEdit = "false";
var paramList = store.getTiddlerText("Infobox_"+ Type.replace(/[\s]/g, "_") + "##Content");
var paramListParsed = paramList.replace(/----\n/g, "").replace(/ /g, "_").split("\n"); //Get parameters
var paramCount = 0;
var param;
var k;
for (k = 0; k < paramListParsed.length; k++) {
if (paramListParsed[k].indexOf("((") !== -1) { //Params when there is a shorthand definition
param = getParam(params, paramListParsed[k].replace(/^[\W\w\s]*?\(\(|\)\)[\W\w\s]*?$/g, ""), 'unknown');
}
else { //Params when there is no shorthand definition
param = getParam(params, paramListParsed[k].replace(/_\*\*[\W\w\s]*?$/g, ""), 'unknown');
}
//Output for section titles
if (paramListParsed[k].indexOf("Section-") !== -1) {
out += "</table><table id=\"SectionTable" + TTIX + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxTable\"><tr id=\"SectionHeader" + TTIX + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\"><td class=\"InfoboxSection Infobox" + TypeX + "Subtitle\" colspan=\"2\">" + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "").replace(/_/g, " ") + "</td></tr>";
outEdit += "</table><table id=\"EditSectionTable" + TTIX + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxTable\"><tr id=\"EditSectionHeader" + TTIX + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\"><td class=\"InfoboxSection Infobox" + TypeX + "Subtitle\" colspan=\"2\">" + paramListParsed[k].replace(/Section-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "").replace(/_/g, " ") + "</td></tr>";
}
//Output for images
else if (paramListParsed[k].indexOf("Image-") !== -1) {
out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/Image-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellImage\" colspan=\"2\"><a href=\"" + param + "\"><img src=\"" + param + "\" alt=\"" + param + "\" title=\"" + param + "\" class=\"InfoboxImage\"/></a></td></tr>";
outEdit += "<tr id=\"Edit" + TTIX + paramListParsed[k].replace(/Image-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellLeft\">Image: " + paramListParsed[k].replace(/_/g, " ").replace(/Image-| \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</td><td class=\"InfoboxCellRight\"><span id=\"EditComment" + TTIX + paramListParsed[k].replace(/Image-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EditComment\">" + paramListParsed[k].replace(/Image-[\w\W\s]*?\*\*/g, "").replace(/_/g, " ").replace(/Image-[\w\W\s]*?$/g, "No comment available.") + "</span><textarea id=\"EditTextarea" + TTIX + paramListParsed[k].replace(/Image-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus'; this.previousSibling.style.display = 'block';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value; this.previousSibling.style.display = 'none';\">" + param + "</textarea></td></tr>";
}
//Output for single cells
else if (paramListParsed[k].indexOf("Single-") !== -1) {
out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellSingle\" colspan=\"2\">" + param + "</td></tr>";
outEdit += "<tr id=\"Edit" + TTIX + paramListParsed[k].replace(/Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellLeft\">Single: " + paramListParsed[k].replace(/_/g, " ").replace(/Single-| \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</td><td class=\"InfoboxCellRight\"><span id=\"EditComment" + TTIX + paramListParsed[k].replace(/Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EditComment\">" + paramListParsed[k].replace(/Single-[\w\W\s]*?\*\*/g, "").replace(/_/g, " ").replace(/Single-[\w\W\s]*?$/g, "No comment available.") + "</span><textarea id=\"EditTextarea" + TTIX + paramListParsed[k].replace(/Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus'; this.previousSibling.style.display = 'block';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value; this.previousSibling.style.display = 'none';\">" + param + "</textarea></td></tr>";
}
//Start output if using sides (left cell)
else if (paramListParsed[k].indexOf("Side1-") !== -1) {
out += "<tr id=\"Content" + TTIX + paramListParsed[k-1].replace(/Section-|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellEqual\">" + param + "</td>";
outEdit += "<tr id=\"EditContent" + TTIX + paramListParsed[k-1].replace(/Section-|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellEqual\"><span id=\"EqualEditParam" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EqualEditParamName\">" + paramListParsed[k].replace(/_/g, " ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</span><span id=\"EditComment" + TTIX + paramListParsed[k].replace(/Side1-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EditComment\">" + paramListParsed[k].replace(/Side1-[\w\W\s]*?\*\*/g, "").replace(/_/g, " ").replace(/Side1-[\w\W\s]*?$/g, "No comment available.") + "</span><textarea id=\"EditTextarea" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus'; this.previousSibling.style.display = 'block';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value; this.previousSibling.style.display = 'none';\">" + param + "</textarea></td>";
}
//End output if using sides (right cell)
else if (paramListParsed[k].indexOf("Side2-") !== -1) {
out += "<td class=\"InfoboxCellEqual\">" + param + "</td></tr>";
outEdit += "<td class=\"InfoboxCellEqual\"><span id=\"EqualEditParam" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EqualEditParamName\">" + paramListParsed[k].replace(/_/g, " ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</span><span id=\"EditComment" + TTIX + paramListParsed[k].replace(/Side2-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EditComment\">" + paramListParsed[k].replace(/Side2-[\w\W\s]*?\*\*/g, "").replace(/_/g, " ").replace(/Side2-[\w\W\s]*?$/g, "No comment available.") + "</span><textarea id=\"EditTextarea" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus'; this.previousSibling.style.display = 'block';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value; this.previousSibling.style.display = 'none';\">" + param + "</textarea></td></tr>";
}
//Normal output
else {
out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellLeft\">" + paramListParsed[k].replace(/_/g, " ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</td><td class=\"InfoboxCellRight\">" + param + "</td></tr>";
outEdit += "<tr id=\"Edit" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxRow\"><td class=\"InfoboxCellLeft\">" + paramListParsed[k].replace(/_/g, " ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "</td><td class=\"InfoboxCellRight\"><span id=\"EditComment" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"EditComment\">" + paramListParsed[k].replace(/^/, "dummy").replace(/dummy[\w\W\s]*?\*\*/g, "").replace(/_/g, " ").replace(/dummy[\w\W\s]*?$/g, "No comment available.") + "</span><textarea id=\"EditTextarea" + TTIX + paramListParsed[k].replace(/_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + "\" class=\"InfoboxEditTextarea\" onfocus=\"this.className = 'InfoboxEditTextareaOnfocus'; this.previousSibling.style.display = 'block';\" onblur=\"this.className = 'InfoboxEditTextareaOnblur'; this.defaultValue = this.value; this.previousSibling.style.display = 'none';\">" + param + "</textarea></td></tr>";
}
//Hide lines with no information
if ((param === "unknown") && (paramListParsed[k].indexOf("Section-") === -1)) {
setStylesheet("#" + TTIX + paramListParsed[k].replace(/Image-|Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + " {display: none !important;}", "InfoboxContentRows" + TTIX + paramListParsed[k].replace(/Image-|Single-|\(\([\w\s]*?\)\)|\*\*[\w\W\s]*?$| /g, ""));
} else {
setStylesheet("#" + TTIX + paramListParsed[k].replace(/Image-|Single-|_\(\([\w\s]*?\)\)|_\*\*[\w\W\s]*?$/g, "") + " {display: table-row;}", "InfoboxContentRows" + TTIX + paramListParsed[k].replace(/Image-|Single-|\(\([\w\s]*?\)\)|\*\*[\w\W\s]*?| /g, ""));
}
//Hide the whole table if all parameters are unknown
if (param === "unknown") { //First count how many params are unknown
paramCount = paramCount + 1;
}
if (paramCount === paramListParsed.length) { //If all params are unknown
setStylesheet("#DivContainer" + TTIX + " {display: none;}", "InfoboxTable" + TTIX);
setStylesheet("#NoInfo" + TTIX + " {display: block;}", "NoInfo" + TTIX);
} else {
setStylesheet("#DivContainer" + TTIX + " {display: block;}", "InfoboxTable" + TTIX);
setStylesheet("#NoInfo" + TTIX + " {display: none;}", "NoInfo" + TTIX);
}
} //End parsing of parameters for output
//Hide section title if all params in the section are unknown (requires extra parsing of parameters by sections)
var section = paramList.replace(/Section-[\w\W\s]*?/g, "").replace(/ /g, "_").split("\n----\n"); //Get sections
var sectionParsed, sectionParams;
var sectionParamCount = 0;
var p, q;
if (section.length > 1) {
for (p = 0; p < section.length; p++) {
sectionParsed = section[p].split("\n"); //Split sections into parameters
for (q = 0; q < sectionParsed.length; q++) { //Parse the parameters
if (sectionParsed[q].indexOf("((") !== -1) { //Params when there is a shorthand definition
sectionParams = getParam(params, sectionParsed[q].replace(/^[\W\w\s]*?\(\(|\)\)[\W\w\s]*?$/g, ""), 'unknown');
}
else { //Params when there is no shorthand definition
sectionParams = getParam(params, sectionParsed[q].replace(/_\*\*[\W\w\s]*?$/g, ""), 'unknown');
}
if (sectionParams === "unknown") { //Count how many parameters in the section are unknown
sectionParamCount = sectionParamCount + 1;
}
}
if (sectionParamCount === sectionParsed.length) {
setStylesheet("#SectionTable" + TTIX + sectionParsed[0].replace(/Section-|_\*\*[\w\W\s]*?$/g, "") + " {display: none;}", "InfoboxSection" + TTIX + sectionParsed[0].replace(/Section-|_\*\*[\w\W\s]*?$/g, ""));
} else {
setStylesheet("#SectionTable" + TTIX + sectionParsed[0].replace(/Section-|_\*\*[\w\W\s]*?$/g, "") + " {display: block;}", "InfoboxSection" + TTIX + sectionParsed[0].replace(/Section-|_\*\*[\w\W\s]*?$/g, ""));
}
sectionParamCount = 0; //Reset the count for the next section
}
}
//Final output
wikify(start + out + end, infoboxTableDiv);
wikify(startEdit + outEdit + endEdit, infoboxTableEditDiv);
} //End if Type is okay
}; //End of Infobox macro
//Toggle display of infoboxes
config.macros.infobox.toggleInfobox = function(editButton,toggleButton,place) {
var hideInfoboxes = config.options.chkHideInfoboxes;
if (hideInfoboxes === true) {
if (place.style.display === "block"){
place.style.display = "none";
editButton.style.display = "none";
toggleButton.innerHTML = toggleButton.getAttribute("closedtext");
toggleButton.setAttribute("title",toggleButton.getAttribute("closedtip"));
} else {
place.style.display = "block";
editButton.style.display = "block";
toggleButton.innerHTML = toggleButton.getAttribute("openedtext");
toggleButton.setAttribute("title",toggleButton.getAttribute("openedtip"));
}
} else {
if (place.style.display === "none") {
place.style.display = "block";
editButton.style.display = "block";
toggleButton.innerHTML = toggleButton.getAttribute("openedtext");
toggleButton.setAttribute("title",toggleButton.getAttribute("openedtip"));
} else {
place.style.display = "none";
editButton.style.display = "none";
toggleButton.innerHTML = toggleButton.getAttribute("closedtext");
toggleButton.setAttribute("title",toggleButton.getAttribute("closedtip"));
}
}
};
//End toggle display of infoboxes
//Edit infoboxes
config.macros.infobox.editInfobox = function(saveButton,editButton,deleteButton,toggleButton,place,placeEdit,tiddler,noEdit) {
if (noEdit === "false") {
if (place.style.display === "block"){
deleteButton.style.display = "block";
saveButton.style.display = "block";
toggleButton.style.display = "none";
place.style.display = "none";
placeEdit.style.display = "block";
editButton.innerHTML = editButton.getAttribute("canceltext");
editButton.setAttribute("title",editButton.getAttribute("canceltip"));
}
else {
deleteButton.style.display = "none";
saveButton.style.display = "none";
toggleButton.style.display = "block";
place.style.display = "block";
placeEdit.style.display = "none";
editButton.innerHTML = editButton.getAttribute("edittext");
editButton.setAttribute("title",editButton.getAttribute("edittip"));
story.refreshTiddler(tiddler, null, true);
}
}
};
//End edit infoboxes
//Delete infoboxes
config.macros.infobox.deleteInfobox = function(type,title,instance) {
var confirmDelete = confirm("Do you really want to delete this infobox?\nTitle: \""+title+"\"\nType: \""+type+"\"\nInstance ID: \""+instance+"\"");
if (confirmDelete === true) {
//Get macro
var articleText = store.getTiddlerText(title); //Get article text
var macros = articleText.match(/<<infobox[\w\W\s]*?Type:"[\w\s]*?"[\w\W\s]*?>>/g); //Get all macros
var i;
var targetMacro;
for (i = 0; i < macros.length; i++) { //Get the correct macro
var macroType = "Type:\""+type+"\"";
if (macros[i].match(macroType)) {
if (macros[i].match(instance)) {
var macroInstancID = "InstanceID:\""+instance+"\"";
if (macros[i].match(macroInstancID)) {
targetMacro = macros[i];
}
}
else {
targetMacro = macros[i];
}
}
}
//Delete
var tid = store.getTiddler(title);
var tags = tid.tags;
var oldText;
var oldTextCheck = articleText.match(targetMacro+"\n");
if (oldTextCheck === null) {
oldText = targetMacro;
}
else {
oldText = targetMacro+"\n";
}
var newText = articleText.replace(oldText, "");
store.saveTiddler(title,title,newText,config.options.txtUserName,new Date(),tags);
autoSaveChanges(null,[tiddler]);
story.displayTiddler(null,title);
}
else {
return;
}
};
//End delete infoboxes
//Save infoboxes
config.macros.infobox.saveInfobox = function(saveButton,editButton,deleteButton,toggleButton,place,placeEdit,type,title,instance) {
var savePrompt = config.options.chkSavePrompt;
var doSave;
if (savePrompt === true) {
var confirmSave = confirm("Do you really want to save changes to this infobox?\nTitle: \""+title+"\"\nType: \""+type+"\"\nInstance ID: \""+instance+"\"");
if (confirmSave === true) {
doSave = true;
}
else {
doSave = false;
}
}
else {
doSave = true;
}
if (doSave === true) {
//Get the rendered content
var macroContent = placeEdit.innerHTML.replace(/<td[^>]*?colspan[^>]*?>[\w\W\s]*?<\/td>|<span[^>]*?EditComment[^>]*?>[\w\W\s]*?<\/span>|<span>|<\/span>/g, "").replace(/<\/textarea>/g, "\"\n").replace(/<textarea [\w\W\s]*?>/g, ":\"").replace(/<td[^>]*?>Type<\/td>/g, "Type:\"").replace(/<td[^>]*?>Title<\/td>/g, "\"\nTitle").replace(/<[\w\W\s]*?>|<\/[\w\W\s]*?>/g, "").replace(/Image: /g, "Image-").replace(/Single: /g, "Single-").replace(/Instance ID/g, "InstanceID"); //The "span" tags need to be removed, because they are added by HTMLFormattingPlugin, which is why comments and double cell columns are removed first
//Get the correct macro
var articleText = store.getTiddlerText(title); //Get article text
var macros = articleText.match(/<<infobox[\w\W\s]*?Type:"[\w\s]*?"[\w\W\s]*?>>/g);
var i;
var targetMacro;
for (i = 0; i < macros.length; i++) {
var macroType = "Type:\""+type+"\"";
if (macros[i].match(macroType)) {
if (macros[i].match(instance)) {
var macroInstancID = "InstanceID:\""+instance+"\"";
if (macros[i].match(macroInstancID)) {
targetMacro = macros[i];
}
}
else {
targetMacro = macros[i];
}
}
}
//Remove sections from the rendered content
var template = "Infobox_" + type.replace(/ /g, "_"); //Get template name
var templateText = store.getTiddlerText(template + "##Content"); //Get template definition
var templateSection = templateText.match(/Section-[\w\W\s]*?\n/g); //Get sections
var templateSectionCleaned = [];
var sectionCleaned, targetMacroSectionsReplace;
var j;
for (j = 0; j < templateSection.length; j++) {
sectionCleaned = templateSection[j].replace(/Section-| \*\*[\w\W\s]*?\n/g, ""); //Clean up sections
targetMacroSectionsReplace = sectionCleaned+"\"\\n";
if (macroContent.match(sectionCleaned)) {
templateSectionCleaned.push(targetMacroSectionsReplace); //Add all containd sections to array
}
}
var templateSectionCleanedString = new RegExp(templateSectionCleaned.toString().replace(/,/g, "|"), "g"); //Convert the array to string to be used in regexp
var macroContentSectionsCleaned = macroContent.replace(templateSectionCleanedString, ""); //Remove the sections from the macro
//Remove unknown parameters from the rendered content
var templateParams = templateText.replace(/----\n|Section-[\w\W\s]*?\n/g, "").replace(/ \*\*[\w\W\s]*?\n/g, "\n").split("\n"); //Get parameters
var templateParamsCleaned = [];
var shorthands = [];
var paramsCleaned, targetMacroParamsReplaceUnknown, targetMacroParamsReplaceEmpty, longhand, shorthand;
var k;
for (k = 0; k < templateParams.length; k++) { //Clean up parameters
if (templateParams[k].indexOf("((") !== -1) { //Get shorthand definitions for later
longhand = templateParams[k].replace(/Image-|Single-|Side1-|Side2-| \(\([\W\w\s]*?$/g, "");
shorthand = templateParams[k].replace(/^[\W\w\s]*?\(\(|\)\)[\W\w\s]*?$/g, "");
shorthands.push(longhand);
shorthands.push(shorthand);
}
paramsCleaned = templateParams[k].replace(/ \(\([\W\w\s]*?$|\n/g, ""); //Remove shorthand definitions and comments
targetMacroParamsReplaceUnknown = paramsCleaned+":\"unknown\"\\n";
if (macroContent.match(targetMacroParamsReplaceUnknown)) {
templateParamsCleaned.push(targetMacroParamsReplaceUnknown); //Add all contained unknown params to array
}
targetMacroParamsReplaceEmpty = paramsCleaned+":\"\"\\n";
if (macroContent.match(targetMacroParamsReplaceEmpty)) {
templateParamsCleaned.push(targetMacroParamsReplaceEmpty); //Add all contained empty params to array
}
}
var templateParamsCleanedString = new RegExp(templateParamsCleaned.toString().replace(/,/g, "|"), "g"); //Convert the array to string to be used in regexp
var macroContentParamsCleaned = macroContentSectionsCleaned.replace(templateParamsCleanedString, ""); //Remove the unknown params from the macro
//Replace longhand parameters with shorthands
var macroContentParamsCleanedSplit = macroContentParamsCleaned.split("\n"); //Convert macro string to array
var macroContentShorthandsArray = [];
var m, n;
var macroContentParamsClean, shorthandReplacement;
for (m = 0; m < macroContentParamsCleanedSplit.length; m++) { //Find out which parameters have shorthand definition
macroContentParamsClean = macroContentParamsCleanedSplit[m].replace(/Image-|Single-|Side1-|Side2-|:"[\w\W\s]*?"/g, "");
shorthandReplacement = "none";
for (n = 0; n < shorthands.length; n = n + 2) {
if (macroContentParamsClean === shorthands[n]) {
shorthandReplacement = macroContentParamsCleanedSplit[m].replace(/Image-|Single-|Side1-|Side2-/g, "").replace(shorthands[n], shorthands[n+1]); //Replace longhand parameters with shorthands
}
}
if (shorthandReplacement === "none") {
shorthandReplacement = macroContentParamsCleanedSplit[m];
}
macroContentShorthandsArray.push(shorthandReplacement); //Add all parameters to array
}
var macroContentShorthands = macroContentShorthandsArray.toString().replace(/",/g, "\"\n"); //Convert the array back to string
//Remove instance ID
var removeInstanceID = macroContentShorthands.replace(/InstanceID:"DefaultID"\n/, "");
//Remove title from the rendered content if it's the tiddler title and it isn't already in the macro
var defaultTitle = "Title:\""+title+"\"";
var removeTitleRE = defaultTitle+"\n";
var removeTitle;
if (!targetMacro.match(defaultTitle)) {
removeTitle = removeInstanceID.replace(removeTitleRE, "");
}
else {
removeTitle = removeInstanceID;
}
//Replace spaces in params with underscores
var matchSpaces = removeTitle.match(/^[\w\W\s]*?:|\n[\w\W\s]*?:/g); //Get the parameter names
var matchContent = removeTitle.match(/"[\w\W\s]*?"/g); //Get the parameter values
var replaceSpaces = [];
var l;
for (l = 0; l < matchSpaces.length; l++) {
replaceSpaces.push(matchSpaces[l].replace(/ /g, "_") + matchContent[l]); //Rejoin the parameter names and values
}
var noSpaces = replaceSpaces.toString().replace(/,/g, "");
//Add start and end macro code
var fullCode = "<<infobox\n" + noSpaces + "\n>>";
var addCode;
var saveMode = config.options.chkSaveMode;
if (saveMode === true) {
addCode = fullCode;
}
else {
addCode = fullCode.replace(/[\s]*?\n|\n[\s]*?|\n/g, " ").replace(/ >>/, ">>");
}
//Save
var tid = store.getTiddler(title);
var tags = tid.tags;
var newText = articleText.replace(targetMacro, addCode);
store.saveTiddler(title,title,newText,config.options.txtUserName,new Date(),tags);
autoSaveChanges(null,[tiddler]);
story.displayTiddler(null,title);
//Toggle display
editButton.style.display = "block";
deleteButton.style.display = "none";
saveButton.style.display = "none";
toggleButton.style.display = "block";
place.style.display = "block";
placeEdit.style.display = "none";
}
else {
return;
}
};
//End save of infoboxes
//}}}
//{{{
} //End of install only once
//}}}
/***
|Name|[[InfoboxTablesPlugin]]|
|Source|[[InfoboxTablesPlugin]]|
|Documentation|[[InfoboxTablesPluginInfo]]|
|Version|(2.0.0) ALPHA/INCOMPLETE|
|Author|Kristjan Brezovnik|
|License||
|~CoreVersion|2.1|
|Requires||
|Makes use of|[[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]]<br>[[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]]|
|Type|plugin|
|Description|Provides infoboxes for different types of articles.|
***/
/***
!To Do
*Check why InfoboxTable class is not applied correctly (style attribute is required for some parameters instead of using class attribute)
*Display warning when InstanceIDs are duplicated
*InfoCellLeft and InfoCellRight get squeezed to InfoCellEqual width in Waterfox, Chrome and Safari, in IE and Opera, all columns are the same width - try using <col span="2"/>
*Add InfoboxInfo mechanism
**Add xxxInfoboxParams to InfoboxInfo, to enable copying of params when entering info
**config.shadowTiddlers.ToolbarCommands.replace(/ViewToolbar\|/,"ViewToolbar\|InfoboxInfo"); - for adding to EditToolbar
*Maybe change checking for sections and pasing of parameters, so that parameters are only parsed once
***/
/***
!Configuration
<<option chkUseNestedSlidersPlugin>> Use [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]], if it's installed
<<option chkUseHTMLFormattingPlugin>> Use [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]], if it's installed ([[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] must be installed and enabled as well)
***/
/***
!Code
***/
//{{{
//Ensure that the plugin is only installed once
if (!version.extensions.InfoboxTablesPlugin) {
version.extensions.InfoboxTablesPlugin = {installed: true};
version.extensions.InfoboxTablesPlugin = {major: 2, minor: 0, revision: 0, date: new Date(2012,3,13)};
//Use NestedSlidersPlugin and HTMLFormattingPlugin, if they're installed
if (config.options.chkUseNestedSlidersPlugin === undefined) {config.options.chkUseNestedSlidersPlugin = true;}
if (config.options.chkUseHTMLFormattingPlugin === undefined) {config.options.chkUseHTMLFormattingPlugin = true;}
//}}}
/***
!!Generic Color Palette
***/
//{{{
config.shadowTiddlers.InfoboxTablesColorPalette =
"InfoboxTableBackground: whitesmoke\n" +
"InfoboxTableTopColor: whitesmoke\n" +
"InfoboxTypeError: red\n";
//}}}
/***
!!Generic Stylesheet
***/
//{{{
config.shadowTiddlers.InfoboxTablesStylesheet =
".InfoboxTable {border-collapse: separate; border: none 0px; border-spacing: 0px; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; width: 300px; font-size: 10px; font-weight: bold; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n"+
".InfoboxTableTop, .InfoboxTableBottom {text-align: center; font-size: 16px; line-height:120%}\n" +
".InfoboxTableTop {border: none 0px; border-radius: 10px 10px 0px 0px; -moz-border-radius: 10px 10px 0px 0px; -webkit-border-radius: 10px 10px 0px 0px;}\n" +
".InfoboxTableBottom {border: none 0px; border-radius: 0px 0px 10px 10px; -moz-border-radius: 0px 0px 10px 10px; -webkit-border-radius: 0px 0px 10px 10px;}\n" +
".InfoboxCellLeft, .InfoboxCellRight, .InfoboxCellEqual, .InfoboxCellImage {font-weight: normal; border: 1px solid; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]}\n"+
".InfoboxCellLeft {width: 100px;}\n" +
".InfoboxCellRight {width: 200px;}\n" +
".InfoboxCellEqual {width: 150px;}\n" +
".InfoboxCellImage {width: 300px; text-align: center;}\n" +
"img.InfoboxImage {max-width: 290px;}\n" +
"#displayArea .viewer a.NestedSliderButton {border: 1px solid black; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]; padding: 1px; margin: 1px;} /* This makes the label/tooltip from the NestedSlidersPlugin look like a button */\n" +
".FloatRight {float: right;}\n" +
".SmallButton {font-size: 10px; line-height: 120%;}\n" +
".InfoboxTypeError {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//}}}
/***
!!Specific Color Palette, Stylesheet, Info
***/
//{{{
var list = store.getTaggedTiddlers("infobox");
var listTitle, listContent, listColors, listColorsTitle, listColorsSubtitle, paramListInfo, paramListInfoParsed;
var i, j;
var validTypes = "";
config.shadowTiddlers.InfoboxTablesInfo = "";
for (i = 0; i < list.length; i++) {
listTitle = list[i].title.replace(/Infobox|_| /g, "");
validTypes += list[i].title.replace(/Infobox_/, "").replace(/_/g, " ") + ", ";
listContent = store.getTiddlerText(list[i].title + "##Content");
listColorsTitle = store.getTiddlerText(list[i].title + "::Title");
listColorsSubtitle = store.getTiddlerText(list[i].title + "::Subtitle");
//Color Palette
config.shadowTiddlers.InfoboxTablesColorPalette +=
"Infobox" + listTitle + "Title: " + listColorsTitle + "\n" +
"Infobox" + listTitle + "Subtitle: " + listColorsSubtitle + "\n";
//Stylesheet
config.shadowTiddlers.InfoboxTablesStylesheet +=
".Infobox" + listTitle + "Title {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]];}\n" +
".Infobox" + listTitle + "Subtitle {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Subtitle]];}\n" +
".NoInfo" + listTitle + " {width: 300px; background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; font-weight: bold; border: solid 2px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n" +
".Infobox" + listTitle + "Error {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//Info
paramListInfo = listContent.split("\n");
paramListInfoParsed = "";
for (j = 0; j < paramListInfo.length; j++) {
if (paramListInfo[j].indexOf("Section-") === -1) {
paramListInfoParsed += paramListInfo[j].replace(/Image-|Side1-|Side2-/g, "") + "\n";
}
}
config.shadowTiddlers.InfoboxTablesInfo +=
"!" + listTitle.toLowerCase() + "InfoboxInfo\n" + paramListInfoParsed;
}
//}}}
/***
!!Infobox Macro
***/
//{{{
config.macros.infobox = {};
config.macros.infobox.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
params = paramString.parseParams(null, null, true);
var Type = getParam(params, 'Type', 'unknown');
var Title = getParam(params, 'Title', tiddler.title);
var InstanceID = getParam(params, 'InstanceID', '_DefaultID');
var TypeX = Type.replace(/[\s]/g, "");
var TitleX = Title.replace(/[\W\s]/g, "");
var InstanceIDX = InstanceID.replace(/[\s\W]/g, "");
//Output for beginning of table
var startNSP = "{{FloatRight{++++{{NestedSliderButton{[Show infobox|Show infobox][Hide infobox|Hide infobox]}}}<html><table id=\"Table" + TypeX + TitleX + InstanceIDX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"2\">" + Title + "</td></tr>";
var start = "{{FloatRight{<html><table id=\"Table" + TypeX + TitleX + InstanceIDX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"2\">" + Title + "</td></tr>";
//Output for content of table
var out = "";
//Output for end of table
var endNSPHFP = "<tr id=\"Info" + TypeX + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\">{{SmallButton{+++^*{{NestedSliderButton{[Show info|Show info][Hide info|Hide info]}}}...<<tiddler [[InfoboxTablesInfo##" + Type.toLowerCase().replace(/ /g, "") + "InfoboxInfo]]>>===}}}</td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var endNSP = "<tr id=\"Info" + TypeX + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\"> </td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var end = "<tr id=\"Info" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\"> </td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>}}}";
//If Type is missing
if (Type === "unknown" || Type === null || Type.length === 0) {
wikify("{{InfoboxTypeError{\nType is mandatory! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is wrong
else if (validTypes.indexOf(Type) === -1) {
wikify("{{InfoboxTypeError{\nYou entered a non-existent type! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is okay
else if (validTypes.indexOf(Type) !== -1) {
//Check how many instances of the same type there are in a tiddler
var instanceCheck = store.getTiddlerText(tiddler.title);
var instanceInfobox = instanceCheck.match(/<<infobox/g); //Find all instances of the macro in the tiddler
if (instanceInfobox.length > 1) { //If there is more than one instance
var instanceInfoboxType = instanceCheck.match(/<<infobox[\w\W\n]*?Type:"[\w\s]*?"[\w\W\n]*?>>/g); //Get all infoboxes
var instanceInfoboxTypeResultEmpty = [];
var instanceInfoboxTypeResult = [];
var l;
for (l = 0; l < instanceInfoboxType.length; l++) {
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && (InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and does not have an InstanceID parameter, put it into array
instanceInfoboxTypeResultEmpty.push(instanceInfoboxType[l]);
}
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && !(InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and has an InstanceID parameter, put it into array
instanceInfoboxTypeResult.push(instanceInfoboxType[l]);
}
}
if (instanceInfoboxTypeResultEmpty.length > 1) { //If there is more than one infobox without athe InstanceID parameter
var instanceIDCount = 0;
var m;
for (m = 0; m < instanceInfoboxTypeResultEmpty.length; m++) { //Count the number or missing InstanceID parameters
if (instanceInfoboxTypeResultEmpty[m].match(/InstanceID:"[\w\s]*?"/g) !== null) {
instanceIDCount = instanceIDCount + 1;
}
}
if (instanceInfoboxType.length > instanceIDCount) { //If there are more infoboxes than InstanceID parameters per type
if (InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) { //Display error message for all infoboxes without an InstanceID parameter
wikify("{{Infobox" + TypeX + "Error{\nThere are " + instanceInfoboxTypeResultEmpty.length + " infoboxes of \"" + Type + "\" type, but " + instanceIDCount + " ~IDs. This infobox does not have an ''~InstanceID'' parameter.<br/>When using more than one infobox of the same type, you need to add ''~InstanceID'' parameter to all of them. This parameter can be a random ''alphanumeric'' string and must be different for each infobox of the same type.}}}", place);
return;
}
}
} //End missing check
//Check for duplicate InstanceID parameters for a type
var instanceIDs = [];
var instanceIDMatch;
var n;
if (instanceInfoboxTypeResult.length > 1) { //If there is more than one infobox with the InstanceID parameter
for (n = 0; n < instanceInfoboxTypeResult.length; n++) { //Count the number or InstanceID parameters
if ((instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g) !== null) && !(InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0)) {
instanceIDMatch = instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g);
instanceIDs.push(instanceIDMatch);
}
}
var instanceIDsSorted = instanceIDs.sort();
var duplicateIDs = [];
var o;
for (o = 0; o < instanceIDsSorted.length - 1; o++) { //Find the duplicates
if (instanceIDsSorted[o+1] === instanceIDsSorted[o]) {
duplicateIDs.push(instanceIDsSorted[o]);
}
}
if (duplicateIDs.length > 1) {
wikify("{{Infobox" + TypeX + "Error{\nThis infobox has the same ''~InstanceID'' parameter (\"" + InstanceID + "\") as another infobox of the same type (\"" + Type + "\").<br/>Infoboxes of the same type must have ''unique ~IDs''.}}}", place);
return;
}
} //End duplicate check
} //End of checks when there's more than one instance
//Begin parsing parameters for output
var paramList = store.getTiddlerText("Infobox_"+ Type.replace(/[\s]/g, "_") + "##Content");
var paramListParsed = paramList.replace(/----\n/g, "").replace(/ /g, "_").split("\n"); //Get parameters
var paramCount = 0;
var param;
var k;
for (k = 0; k < paramListParsed.length; k++) {
param = getParam(params, paramListParsed[k], 'unknown');
//Output for section titles
if (paramListParsed[k].indexOf("Section-") !== -1) {
out += "<tr id=\"Section" + TitleX + paramListParsed[k].replace(/Section-/g, "") + InstanceIDX + "\"><td class=\"Infobox" + TypeX + "Subtitle\" colspan=\"2\">" + paramListParsed[k].replace(/Section-|\*\*[\w\W]*?$/g, "").replace(/_/g, " ") + "</td></tr>";
}
//Output for images
else if (paramListParsed[k].indexOf("Image-") !== -1) {
out += "<tr id=\"" + TitleX + paramListParsed[k].replace(/Image-/g, "") + InstanceIDX + "\"><td class=\"InfoboxCellImage\" colspan=\"2\"><img src=\"" + param + "\" alt=\"" + param + "\" title=\"" + param + "\" class=\"InfoboxImage\"/></td></tr>";
}
//Start output if using sides (left cell)
else if (paramListParsed[k].indexOf("Side1-") !== -1) {
out += "<tr id=\"" + TitleX + paramListParsed[k-1].replace(/Section-/g, "") + "Content" + InstanceIDX + "\"><td id=\"" + TitleX + paramListParsed[k].replace(/Side1-/g, "") + InstanceIDX + "\" class=\"InfoboxCellEqual\">" + param + "</td>";
}
//End output if using sides (right cell)
else if (paramListParsed[k].indexOf("Side2-") !== -1) {
out += "<td id=\"" + TitleX + paramListParsed[k].replace(/Side2-/g, "") + InstanceIDX + "\" class=\"InfoboxCellEqual\">" + param + "</td></tr>";
}
//Normal output
else {
out += "<tr id=\"" + TitleX + paramListParsed[k].replace(/ /g, "") + InstanceIDX + "\"><td class=\"InfoboxCellLeft\">" + paramListParsed[k].replace(/_/g, " ") + "</td><td class=\"InfoboxCellRight\">" + param + "</td></tr>";
}
//Hide lines with no information
if ((param === "unknown") && (paramListParsed[k].indexOf("Section-") === -1)) {
setStylesheet("#" + TitleX + paramListParsed[k].replace(/ /g, "") + InstanceIDX + " {display: none;}", "Infobox" + TypeX + paramListParsed[k] + TitleX + InstanceIDX);
} else {
setStylesheet("#" + TitleX + paramListParsed[k].replace(/ /g, "") + InstanceIDX + " {display: inherit;}", "Infobox" + TypeX + paramListParsed[k] + TitleX + InstanceIDX);
}
//Hide the whole table if all parameters are unknown
if (param === "unknown") { //First count how many params are unknown
paramCount = paramCount + 1;
}
if (paramCount === paramListParsed.length) { //If all params are unknown
setStylesheet("#Table" + TypeX + TitleX + InstanceIDX + " {display: none;}\n", "Infobox" + TypeX + "Table" + TitleX + InstanceIDX);
setStylesheet("#NoInfo" + TypeX + TitleX + InstanceIDX + " {display: inherit;}", "NoInfo" + TypeX + TitleX + InstanceIDX);
} else {
setStylesheet("#Table" + TypeX + TitleX + InstanceIDX + " {display: inherit;}\n", "Infobox" + TypeX + "Table" + TitleX + InstanceIDX);
setStylesheet("#NoInfo" + TypeX + TitleX + InstanceIDX + " {display: none;}", "NoInfo" + TypeX + TitleX + InstanceIDX);
}
} //End parsing of parameters for output
//Hide section title if all params in the section are unknown (requires extra parsing of parameters by sections)
var section = paramList.replace(/Section-[\w\W\n]*?/g, "").replace(/ /g, "_").split("\n----\n"); //Get sections
var sectionParsed, sectionParams;
var sectionParamCount = 0;
var p, q;
if (section.length > 1) {
for (p = 0; p < section.length; p++) {
sectionParsed = section[p].split("\n"); //Split sections into parameters
for (q = 0; q < sectionParsed.length; q++) { //Parse the parameters
sectionParams = getParam(params, sectionParsed[q], 'unknown');
if (sectionParams === "unknown") { //Count how many parameters in the section are unknown
sectionParamCount = sectionParamCount + 1;
}
}
if (sectionParamCount === sectionParsed.length) {
setStylesheet("#Section" + TitleX + sectionParsed[0].replace(/Section-/g, "") + InstanceIDX + " {display: none;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + InstanceIDX);
} else {
setStylesheet("#Section" + TitleX + sectionParsed[0].replace(/Section-/g, "") + InstanceIDX + " {display: inherit;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + InstanceIDX);
}
sectionParamCount = 0; //Reset the count for the next section
}
}
//Final output
//If NestedSlidersPlugin and HTMLFormattingPlugin are installed and both options are true
if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (version.extensions.HTMLFormattingPlugin && config.options.chkUseHTMLFormattingPlugin === true)) {
wikify(startNSP + out + endNSPHFP, place);
}
//If NestedSlidersPlugin is installed and option is true, HTMLFormattingPlugin is not installed or option is false
else if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (!version.extensions.HTMLFormattingPlugin || config.options.chkUseHTMLFormattingPlugin === false)) {
wikify(startNSP + out + endNSP, place);
}
//If NestedSlidersPlugin and HTMLFormattingPlugin are not installed
else {
wikify(start + out + end, place);
}
}
}; //End of macro
} //End of install only once
//}}}
/***
|Name|[[InfoboxTablesPlugin]]|
|Source|[[InfoboxTablesPlugin]]|
|Documentation|[[InfoboxTablesPluginInfo]]|
|Version|(2.0.0) ALPHA/INCOMPLETE|
|Author|Kristjan Brezovnik|
|License||
|~CoreVersion|2.1|
|Requires||
|Makes use of|[[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]]<br>[[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]]|
|Type|plugin|
|Description|Provides infoboxes for different types of articles.|
***/
/***
!To Do
*Check why InfoboxTable class is not applied correctly (style attribute is required for some parameters instead of using class attribute)
*Display warning when InstanceIDs are duplicated
*InfoCellLeft and InfoCellRight get squeezed to InfoCellEqual width in Waterfox, Chrome and Safari, in IE and Opera, all columns are the same width - try using <col span="2"/>
*Add InfoboxInfo mechanism
**Add xxxInfoboxParams to InfoboxInfo, to enable copying of params when entering info
**config.shadowTiddlers.ToolbarCommands.replace(/ViewToolbar\|/,"ViewToolbar\|InfoboxInfo"); - for adding to EditToolbar
*Maybe change checking for sections and pasing of parameters, so that parameters are only parsed once
* Unify the way the IDs are written and join TypeX + TitleX + InstanceIDX into a single variable
***/
/***
!Configuration
<<option chkUseNestedSlidersPlugin>> Use [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]], if it's installed
<<option chkUseHTMLFormattingPlugin>> Use [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]], if it's installed ([[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] must be installed and enabled as well)
***/
/***
!Code
***/
//{{{
//Ensure that the plugin is only installed once
if (!version.extensions.InfoboxTablesPlugin) {
version.extensions.InfoboxTablesPlugin = {installed: true};
version.extensions.InfoboxTablesPlugin = {major: 2, minor: 0, revision: 0, date: new Date(2012,3,13)};
//Use NestedSlidersPlugin and HTMLFormattingPlugin, if they're installed
if (config.options.chkUseNestedSlidersPlugin === undefined) {config.options.chkUseNestedSlidersPlugin = true;}
if (config.options.chkUseHTMLFormattingPlugin === undefined) {config.options.chkUseHTMLFormattingPlugin = true;}
//}}}
/***
!!Generic Color Palette
***/
//{{{
config.shadowTiddlers.InfoboxTablesColorPalette =
"InfoboxTableBackground: whitesmoke\n" +
"InfoboxTableTopColor: whitesmoke\n" +
"InfoboxTypeError: red\n";
//}}}
/***
!!Generic Stylesheet
***/
//{{{
config.shadowTiddlers.InfoboxTablesStylesheet =
".InfoboxTable {border-collapse: separate; border: none 0px; border-spacing: 0px; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; width: 300px; font-size: 10px; font-weight: bold; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n"+
".InfoboxTableTop, .InfoboxTableBottom {text-align: center; font-size: 16px; line-height: 120%;}\n" +
".InfoboxTableTop {border: none 0px; border-radius: 10px 10px 0px 0px; -moz-border-radius: 10px 10px 0px 0px; -webkit-border-radius: 10px 10px 0px 0px;}\n" +
".InfoboxTableBottom {border: none 0px; border-radius: 0px 0px 10px 10px; -moz-border-radius: 0px 0px 10px 10px; -webkit-border-radius: 0px 0px 10px 10px;}\n" +
".InfoboxCellLeft, .InfoboxCellRight, .InfoboxCellEqual, .InfoboxCellImage {font-weight: normal; border: 1px solid; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n"+
".InfoboxCellLeft {width: 100px;}\n" +
".InfoboxCellRight {width: 200px;}\n" +
".InfoboxCellEqual {width: 150px;}\n" +
".InfoboxCellImage {width: 300px; text-align: center;}\n" +
"img.InfoboxImage {max-width: 290px;}\n" +
"#displayArea .viewer a.NestedSliderButton {border: 1px solid black; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]; padding: 1px; margin: 1px;} /* This makes the label/tooltip from the NestedSlidersPlugin look like a button */\n" +
".FloatRight {float: right;}\n" +
".SmallButton {font-size: 10px; line-height: 120%;}\n" +
".InfoboxTypeError {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//}}}
/***
!!Specific Color Palette, Stylesheet, Info
***/
//{{{
var list = store.getTaggedTiddlers("infobox");
var listTitle, listContent, listColors, listColorsTitle, listColorsSubtitle, paramListInfo, paramListInfoParsed;
var i, j;
var validTypes = "";
config.shadowTiddlers.InfoboxTablesInfo = "";
for (i = 0; i < list.length; i++) {
listTitle = list[i].title.replace(/Infobox|_| /g, "");
validTypes += list[i].title.replace(/Infobox_/, "").replace(/_/g, " ") + ", ";
listContent = store.getTiddlerText(list[i].title + "##Content");
listColorsTitle = store.getTiddlerText(list[i].title + "::Title");
listColorsSubtitle = store.getTiddlerText(list[i].title + "::Subtitle");
//Color Palette
config.shadowTiddlers.InfoboxTablesColorPalette +=
"Infobox" + listTitle + "Title: " + listColorsTitle + "\n" +
"Infobox" + listTitle + "Subtitle: " + listColorsSubtitle + "\n";
//Stylesheet
config.shadowTiddlers.InfoboxTablesStylesheet +=
".Infobox" + listTitle + "Title {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]];}\n" +
".Infobox" + listTitle + "Subtitle {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Subtitle]];}\n" +
".NoInfo" + listTitle + " {width: 300px; background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; font-weight: bold; border: solid 2px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n" +
".Infobox" + listTitle + "Error {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//Info
paramListInfo = listContent.split("\n");
paramListInfoParsed = "";
for (j = 0; j < paramListInfo.length; j++) {
if (paramListInfo[j].indexOf("Section-") === -1) {
paramListInfoParsed += paramListInfo[j].replace(/Image-|Side1-|Side2-/g, "") + "\n";
}
}
config.shadowTiddlers.InfoboxTablesInfo +=
"!" + listTitle.toLowerCase() + "InfoboxInfo\n" + paramListInfoParsed;
}
//}}}
/***
!!Infobox Macro
***/
//{{{
config.macros.infobox = {};
config.macros.infobox.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
params = paramString.parseParams(null, null, true);
var Type = getParam(params, 'Type', 'unknown');
var Title = getParam(params, 'Title', tiddler.title);
var InstanceID = getParam(params, 'InstanceID', '_DefaultID');
var TypeX = Type.replace(/[\s]/g, "");
var TitleX = Title.replace(/[\W\s]/g, "");
var InstanceIDX = InstanceID.replace(/[\s\W]/g, "");
//Output for beginning of table
var startNSP = "{{FloatRight{++++{{NestedSliderButton{[Show infobox|Show infobox][Hide infobox|Hide infobox]}}}<html><table id=\"Table" + TypeX + TitleX + InstanceIDX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"2\">" + Title + "</td></tr>";
var start = "{{FloatRight{<html><table id=\"Table" + TypeX + TitleX + InstanceIDX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"2\">" + Title + "</td></tr>";
//Output for content of table
var out = "";
var outE = "";
//Output for end of table
var endNSPHFP = "<tr id=\"Info" + TypeX + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\">{{SmallButton{+++^*{{NestedSliderButton{[Show info|Show info][Hide info|Hide info]}}}...<<tiddler [[InfoboxTablesInfo##" + TypeX.toLowerCase() + "InfoboxInfo]]>>===}}}</td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var endNSP = "<tr id=\"Info" + TypeX + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\"> </td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var end = "<tr id=\"Info" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"2\"> </td></tr></table><br/><div id=\"NoInfo" + TypeX + TitleX + InstanceIDX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>}}}";
//If Type is missing
if (Type === "unknown" || Type === null || Type.length === 0) {
wikify("{{InfoboxTypeError{\nType is mandatory! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is wrong
else if (validTypes.indexOf(Type) === -1) {
wikify("{{InfoboxTypeError{\nYou entered a non-existent type! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is okay
else if (validTypes.indexOf(Type) !== -1) {
//Check how many instances of the same type there are in a tiddler
var instanceCheck = store.getTiddlerText(tiddler.title);
var instanceInfobox = instanceCheck.match(/<<infobox/g); //Find all instances of the macro in the tiddler
if (instanceInfobox.length > 1) { //If there is more than one instance
var instanceInfoboxType = instanceCheck.match(/<<infobox[\w\W\n]*?Type:"[\w\s]*?"[\w\W\n]*?>>/g); //Get all infoboxes
var instanceInfoboxTypeResultEmpty = [];
var instanceInfoboxTypeResult = [];
var l;
for (l = 0; l < instanceInfoboxType.length; l++) {
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && (InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and does not have an InstanceID parameter, put it into array
instanceInfoboxTypeResultEmpty.push(instanceInfoboxType[l]);
}
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && !(InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and has an InstanceID parameter, put it into array
instanceInfoboxTypeResult.push(instanceInfoboxType[l]);
}
}
if (instanceInfoboxTypeResultEmpty.length > 1) { //If there is more than one infobox without athe InstanceID parameter
var instanceIDCount = 0;
var m;
for (m = 0; m < instanceInfoboxTypeResultEmpty.length; m++) { //Count the number or missing InstanceID parameters
if (instanceInfoboxTypeResultEmpty[m].match(/InstanceID:"[\w\s]*?"/g) !== null) {
instanceIDCount = instanceIDCount + 1;
}
}
if (instanceInfoboxType.length > instanceIDCount) { //If there are more infoboxes than InstanceID parameters per type
if (InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0) { //Display error message for all infoboxes without an InstanceID parameter
wikify("{{Infobox" + TypeX + "Error{\nThere are " + instanceInfoboxTypeResultEmpty.length + " infoboxes of \"" + Type + "\" type, but " + instanceIDCount + " ~IDs. This infobox does not have an ''~InstanceID'' parameter.<br/>When using more than one infobox of the same type, you need to add ''~InstanceID'' parameter to all of them. This parameter can be a random ''alphanumeric'' string and must be different for each infobox of the same type.}}}", place);
return;
}
}
} //End missing check
//Check for duplicate InstanceID parameters for a type
var instanceIDs = [];
var instanceIDMatch;
var n;
if (instanceInfoboxTypeResult.length > 1) { //If there is more than one infobox with the InstanceID parameter
for (n = 0; n < instanceInfoboxTypeResult.length; n++) { //Count the number or InstanceID parameters
if ((instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g) !== null) && !(InstanceID === "_DefaultID" || InstanceID === null || InstanceID.length === 0)) {
instanceIDMatch = instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g);
instanceIDs.push(instanceIDMatch);
}
}
var instanceIDsSorted = instanceIDs.sort();
var duplicateIDs = [];
var o;
for (o = 0; o < instanceIDsSorted.length - 1; o++) { //Find the duplicates
if (instanceIDsSorted[o+1] === instanceIDsSorted[o]) {
duplicateIDs.push(instanceIDsSorted[o]);
}
}
if (duplicateIDs.length > 1) {
wikify("{{Infobox" + TypeX + "Error{\nThis infobox has the same ''~InstanceID'' parameter (\"" + InstanceID + "\") as another infobox of the same type (\"" + Type + "\").<br/>Infoboxes of the same type must have ''unique ~IDs''.}}}", place);
return;
}
} //End duplicate check
} //End of checks when there's more than one instance
//Begin parsing parameters for output
var paramList = store.getTiddlerText("Infobox_"+ Type.replace(/[\s]/g, "_") + "##Content");
var paramListParsed = paramList.replace(/----\n/g, "").replace(/ /g, "_").split("\n"); //Get parameters
var paramCount = 0;
var param;
var k;
for (k = 0; k < paramListParsed.length; k++) {
param = getParam(params, paramListParsed[k], 'unknown');
//Output for section titles
if (paramListParsed[k].indexOf("Section-") !== -1) {
out += "<tr id=\"Section" + TitleX + paramListParsed[k].replace(/Section-/g, "") + InstanceIDX + "\"><td class=\"Infobox" + TypeX + "Subtitle\" colspan=\"2\">" + paramListParsed[k].replace(/Section-|\*\*[\w\W]*?$/g, "").replace(/_/g, " ") + "</td></tr>";
}
//Output for images
else if (paramListParsed[k].indexOf("Image-") !== -1) {
out += "<tr id=\"" + TitleX + paramListParsed[k].replace(/Image-/g, "") + InstanceIDX + "\"><td class=\"InfoboxCellImage\" colspan=\"2\"><img src=\"" + param + "\" alt=\"" + param + "\" title=\"" + param + "\" class=\"InfoboxImage\"/></td></tr>";
}
//Start output if using sides (left cell)
else if ((paramListParsed[k].indexOf("Side1-") !== -1) || (paramListParsed[k].indexOf("Side2-") !== -1)) {
if (paramListParsed[k].indexOf("Side1-") !== -1) {
out += "<tr id=\"" + TitleX + paramListParsed[k-1].replace(/Section-/g, "") + "Content" + InstanceIDX + "\"><td id=\"" + TitleX + paramListParsed[k].replace(/Side1-/g, "") + InstanceIDX + "\" class=\"InfoboxCellEqual\">" + param + "</td>";
}
//End output if using sides (right cell)
else if (paramListParsed[k].indexOf("Side2-") !== -1) {
out += "<td id=\"" + TitleX + paramListParsed[k].replace(/Side2-/g, "") + InstanceIDX + "\" class=\"InfoboxCellEqual\">" + param + "</td></tr>";
}
if (outE.indexOf("</tr>") !== -1) {
//out += outE;
}
}
//Normal output
else {
if ((paramList.indexOf("Side1-") !== -1) || (paramList.indexOf("Side2-") !== -1)) { //If parameters contain Side1- or Side2-
out += "<tr id=\"" + TitleX + paramListParsed[k].replace(/ /g, "") + InstanceIDX + "\"><td class=\"InfoboxCellEqual\">" + paramListParsed[k].replace(/_/g, " ") + "</td><td class=\"InfoboxCellEqual\">" + param + "</td></tr>";
}
else {
out += "<tr id=\"" + TitleX + paramListParsed[k].replace(/ /g, "") + InstanceIDX + "\"><td class=\"InfoboxCellLeft\">" + paramListParsed[k].replace(/_/g, " ") + "</td><td class=\"InfoboxCellRight\">" + param + "</td></tr>";
}
}
//Hide lines with no information
if ((param === "unknown") && (paramListParsed[k].indexOf("Section-") === -1)) {
setStylesheet("#" + TitleX + paramListParsed[k].replace(/Image-| /g, "") + InstanceIDX + " {display: none;}", "Infobox" + TypeX + paramListParsed[k] + TitleX + InstanceIDX);
} else {
setStylesheet("#" + TitleX + paramListParsed[k].replace(/Image-| /g, "") + InstanceIDX + " {display: inherit;}", "Infobox" + TypeX + paramListParsed[k] + TitleX + InstanceIDX);
}
//Hide the whole table if all parameters are unknown
if (param === "unknown") { //First count how many params are unknown
paramCount = paramCount + 1;
}
if (paramCount === paramListParsed.length) { //If all params are unknown
setStylesheet("#Table" + TypeX + TitleX + InstanceIDX + " {display: none;}\n", "Infobox" + TypeX + "Table" + TitleX + InstanceIDX);
setStylesheet("#NoInfo" + TypeX + TitleX + InstanceIDX + " {display: inherit;}", "NoInfo" + TypeX + TitleX + InstanceIDX);
} else {
setStylesheet("#Table" + TypeX + TitleX + InstanceIDX + " {display: inherit;}\n", "Infobox" + TypeX + "Table" + TitleX + InstanceIDX);
setStylesheet("#NoInfo" + TypeX + TitleX + InstanceIDX + " {display: none;}", "NoInfo" + TypeX + TitleX + InstanceIDX);
}
} //End parsing of parameters for output
//Hide section title if all params in the section are unknown (requires extra parsing of parameters by sections)
var section = paramList.replace(/Section-[\w\W\n]*?/g, "").replace(/ /g, "_").split("\n----\n"); //Get sections
var sectionParsed, sectionParams;
var sectionParamCount = 0;
var p, q;
if (section.length > 1) {
for (p = 0; p < section.length; p++) {
sectionParsed = section[p].split("\n"); //Split sections into parameters
for (q = 0; q < sectionParsed.length; q++) { //Parse the parameters
sectionParams = getParam(params, sectionParsed[q], 'unknown');
if (sectionParams === "unknown") { //Count how many parameters in the section are unknown
sectionParamCount = sectionParamCount + 1;
}
}
if (sectionParamCount === sectionParsed.length) {
setStylesheet("#Section" + TitleX + sectionParsed[0].replace(/Section-/g, "") + InstanceIDX + " {display: none;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + InstanceIDX);
setStylesheet(TitleX + sectionParsed[0].replace(/Section-/g, "") + "Content" + InstanceIDX + " {display: none;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + "Content" + InstanceIDX);
} else {
setStylesheet("#Section" + TitleX + sectionParsed[0].replace(/Section-/g, "") + InstanceIDX + " {display: inherit;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + InstanceIDX);
setStylesheet(TitleX + sectionParsed[0].replace(/Section-/g, "") + "Content" + InstanceIDX + " {display: inherit;}", "Infobox" + TypeX + "Section" + sectionParsed[0] + Title.replace(/Section-/g, "") + "Content" + InstanceIDX);
}
sectionParamCount = 0; //Reset the count for the next section
}
}
//Final output
//If NestedSlidersPlugin and HTMLFormattingPlugin are installed and both options are true
if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (version.extensions.HTMLFormattingPlugin && config.options.chkUseHTMLFormattingPlugin === true)) {
wikify(startNSP + out + endNSPHFP, place);
}
//If NestedSlidersPlugin is installed and option is true, HTMLFormattingPlugin is not installed or option is false
else if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (!version.extensions.HTMLFormattingPlugin || config.options.chkUseHTMLFormattingPlugin === false)) {
wikify(startNSP + out + endNSP, place);
}
//If NestedSlidersPlugin and HTMLFormattingPlugin are not installed
else {
wikify(start + out + end, place);
}
}
}; //End of macro
} //End of install only once
//}}}
/***
|Name|[[InfoboxTablesPlugin]]|
|Source|[[InfoboxTablesPlugin]]|
|Documentation|[[InfoboxTablesPluginInfo]]|
|Version|(2.0.0) ALPHA/INCOMPLETE|
|Author|Kristjan Brezovnik|
|License||
|~CoreVersion|2.1|
|Requires||
|Makes use of|[[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]]<br>[[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]]|
|Type|plugin|
|Description|Provides customizable infoboxes for different types of articles.|
***/
/***
!To Do
*Display warning when InstanceIDs are duplicated
*InfoCellLeft and InfoCellRight get squeezed to InfoCellEqual width in Waterfox, Chrome and Safari, in IE and Opera, all columns are the same width
**Lines with Side1/2 parameters don't correctly hide section title in IE, but the table is displayed correctly
*Maybe change checking for sections and passing of parameters, so that parameters are only parsed once
*Check why InfoboxTable class is not applied correctly (style attribute is required for some parameters instead of using class attribute)
*Add InfoboxInfo mechanism
**Add xxxInfoboxParams to InfoboxInfo, to enable copying of params when entering info
**config.shadowTiddlers.ToolbarCommands.replace(/ViewToolbar\|/,"ViewToolbar\|InfoboxInfo"); - for adding to EditToolbar
*Add the option of shorthand for parameters: Participation at important events ((paie)) - ignore stuff in double brackets in Info dropdown; remove )), split by ((, use paramsListParsed(k-1)
***/
/***
!Configuration
<<option chkUseNestedSlidersPlugin>> Use [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]], if it's installed
<<option chkUseHTMLFormattingPlugin>> Use [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]], if it's installed ([[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] must be installed and enabled as well)
***/
/***
!Code
***/
//{{{
//Ensure that the plugin is only installed once
if (!version.extensions.InfoboxTablesPlugin) {
version.extensions.InfoboxTablesPlugin = {installed: true};
version.extensions.InfoboxTablesPlugin = {major: 2, minor: 0, revision: 0, date: new Date(2012,3,13)};
//Use NestedSlidersPlugin and HTMLFormattingPlugin, if they're installed
if (config.options.chkUseNestedSlidersPlugin === undefined) {config.options.chkUseNestedSlidersPlugin = true;}
if (config.options.chkUseHTMLFormattingPlugin === undefined) {config.options.chkUseHTMLFormattingPlugin = true;}
//}}}
/***
!!Generic Color Palette
***/
//{{{
config.shadowTiddlers.InfoboxTablesColorPalette =
"InfoboxTableBackground: whitesmoke\n" +
"InfoboxTableTopColor: whitesmoke\n" +
"InfoboxTypeError: red\n";
//}}}
/***
!!Generic Stylesheet
***/
//{{{
config.shadowTiddlers.InfoboxTablesStylesheet =
".InfoboxTable {border-collapse: separate; border: none 0px; border-spacing: 0px; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; width: 300px; font-size: 10px; font-weight: bold; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n"+
".InfoboxTableTop, .InfoboxTableBottom {text-align: center; font-size: 16px; line-height: 120%;}\n" +
".InfoboxTableTop {border: none 0px; border-radius: 10px 10px 0px 0px; -moz-border-radius: 10px 10px 0px 0px; -webkit-border-radius: 10px 10px 0px 0px;}\n" +
".InfoboxTableBottom {border: none 0px; border-radius: 0px 0px 10px 10px; -moz-border-radius: 0px 0px 10px 10px; -webkit-border-radius: 0px 0px 10px 10px;}\n" +
".InfoboxCellLeft, .InfoboxCellRight, .InfoboxCellEqual, .InfoboxCellImage {font-weight: normal; border: 1px solid; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n"+
".InfoboxCellLeft {width: 100px;}\n" +
".InfoboxCellRight {width: 200px;}\n" +
".InfoboxCellEqual {width: 150px;}\n" +
".InfoboxCellImage {width: 300px; text-align: center;}\n" +
"img.InfoboxImage {max-width: 290px;}\n" +
"#displayArea .viewer a.NestedSliderButton {border: 1px solid black; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]]; padding: 1px; margin: 1px;} /* This makes the label/tooltip from the NestedSlidersPlugin look like a button */\n" +
".FloatRight {float: right;}\n" +
".SmallButton {font-size: 10px; line-height: 120%;}\n" +
".InfoboxTypeError {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px; float: right;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//}}}
/***
!!Specific Color Palette, Stylesheet, Info
***/
//{{{
var list = store.getTaggedTiddlers("infobox");
var listTitle, listContent, listColors, listColorsTitle, listColorsSubtitle, paramListInfo, paramListInfoParsed;
var i, j;
var validTypes = "";
config.shadowTiddlers.InfoboxTablesInfo = "";
for (i = 0; i < list.length; i++) {
listTitle = list[i].title.replace(/Infobox|_| /g, "");
validTypes += list[i].title.replace(/Infobox_/, "").replace(/_/g, " ") + ", ";
listContent = store.getTiddlerText(list[i].title + "##Content");
listColorsTitle = store.getTiddlerText(list[i].title + "::Title");
listColorsSubtitle = store.getTiddlerText(list[i].title + "::Subtitle");
//Color Palette
config.shadowTiddlers.InfoboxTablesColorPalette +=
"Infobox" + listTitle + "Title: " + listColorsTitle + "\n" +
"Infobox" + listTitle + "Subtitle: " + listColorsSubtitle + "\n";
//Stylesheet
config.shadowTiddlers.InfoboxTablesStylesheet +=
".Infobox" + listTitle + "Title {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]];}\n" +
".Infobox" + listTitle + "Subtitle {background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Subtitle]];}\n" +
".NoInfo" + listTitle + " {width: 300px; background: [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; font-weight: bold; border: solid 2px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;}\n" +
".Infobox" + listTitle + "Error {width: 300px; background: [[InfoboxTablesColorPalette::InfoboxTypeError]]; font-weight: bold; border: solid 5px [[InfoboxTablesColorPalette::Infobox" + listTitle + "Title]]; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px; float: right;}\n";
store.addNotification("InfoboxTablesStylesheet", refreshStyles);
//Info
paramListInfo = listContent.split("\n");
paramListInfoParsed = "";
for (j = 0; j < paramListInfo.length; j++) {
if (paramListInfo[j].indexOf("Section-") === -1) {
paramListInfoParsed += paramListInfo[j].replace(/Image-|Side1-|Side2-/g, "") + "\n";
}
}
config.shadowTiddlers.InfoboxTablesInfo +=
"!" + listTitle.toLowerCase() + "InfoboxInfo\n" + paramListInfoParsed;
}
//}}}
/***
!!Infobox Macro
***/
//{{{
config.macros.infobox = {};
config.macros.infobox.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
params = paramString.parseParams(null, null, true);
var Type = getParam(params, 'Type', 'unknown');
var Title = getParam(params, 'Title', tiddler.title);
var InstanceID = getParam(params, 'InstanceID', 'DefaultID');
var TypeX = Type.replace(/[\s]/g, "");
var TitleX = Title.replace(/[\W\s]/g, "");
var InstanceIDX = InstanceID.replace(/[\s\W]/g, "");
var TTIX = TypeX + TitleX + InstanceIDX;
//Output for beginning of table
var startNSP = "{{FloatRight{++++{{NestedSliderButton{[Show infobox|Show infobox][Hide infobox|Hide infobox]}}}<html><table id=\"Table" + TTIX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TTIX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"4\">" + Title + "</td></tr><tr width=\"300\"><td width=\"100\"></td><td width=\"50\"></td><td width=\"50\"></td><td width=\"100\"></td></tr>";
var start = "{{FloatRight{<html><table id=\"Table" + TTIX + "\" class=\"InfoboxTable\" style=\"border-collapse: separate; border: none 0px;\"><tr id=\"Title" + TitleX + InstanceIDX + "\"><td class=\"InfoboxTableTop Infobox" + TypeX + "Title\" colspan=\"4\">" + Title + "</td></tr><tr width=\"300\"><td width=\"100\"></td><td width=\"50\"></td><td width=\"50\"></td><td width=\"100\"></td></tr>";
//Output for content of table
var out = "";
//Output for end of table
var endNSPHFP = "<tr id=\"Info" + TTIX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"4\">{{SmallButton{+++^*{{NestedSliderButton{[Show info|Show info][Hide info|Hide info]}}}...<<tiddler [[InfoboxTablesInfo##" + TypeX.toLowerCase() + "InfoboxInfo]]>>===}}}</td></tr></table><br/><div id=\"NoInfo" + TTIX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var endNSP = "<tr id=\"Info" + TTIX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"4\"> </td></tr></table><br/><div id=\"NoInfo" + TTIX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>===}}}";
var end = "<tr id=\"Info" + TTIX + "\"><td class=\"InfoboxTableBottom Infobox" + TypeX + "Title\" colspan=\"4\"> </td></tr></table><br/><div id=\"NoInfo" + TTIX + "\" class=\"NoInfo" + TypeX + "\">No information available.</div></html>}}}";
//If Type is missing
if (Type === "unknown" || Type === null || Type.length === 0) {
wikify("{{InfoboxTypeError{\nType is mandatory! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is wrong
else if (validTypes.indexOf(Type) === -1) {
wikify("{{InfoboxTypeError{\nYou entered a non-existent type! Allowed types are: " + validTypes.replace(/, $/, "") + "}}}", place);
return;
}
//If Type is okay
else if (validTypes.indexOf(Type) !== -1) {
//Check how many instances of the same type there are in a tiddler
var instanceCheck = store.getTiddlerText(tiddler.title);
var instanceInfobox = instanceCheck.match(/<<infobox/g); //Find all instances of the macro in the tiddler
if (instanceInfobox.length > 1) { //If there is more than one instance
var instanceInfoboxType = instanceCheck.match(/<<infobox[\w\W\n]*?Type:"[\w\s]*?"[\w\W\n]*?>>/g); //Get all infoboxes
var instanceInfoboxTypeResultEmpty = [];
var instanceInfoboxTypeResult = [];
var l;
for (l = 0; l < instanceInfoboxType.length; l++) {
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && (InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and does not have an InstanceID parameter, put it into array
instanceInfoboxTypeResultEmpty.push(instanceInfoboxType[l]);
}
if ((instanceInfoboxType[l].match("Type:\"" + Type + "\"") !== -1) && !(InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) && (instanceInfoboxType[l].indexOf(Type) !== -1)) { //If the infobox matches the type and has an InstanceID parameter, put it into array
instanceInfoboxTypeResult.push(instanceInfoboxType[l]);
}
}
if (instanceInfoboxTypeResultEmpty.length > 1) { //If there is more than one infobox without the InstanceID parameter
var instanceIDCount = 0;
var m;
for (m = 0; m < instanceInfoboxTypeResultEmpty.length; m++) { //Count the number or missing InstanceID parameters
if (instanceInfoboxTypeResultEmpty[m].match(/InstanceID:"[\w\s]*?"/g) !== null) {
instanceIDCount = instanceIDCount + 1;
}
}
if (instanceInfoboxType.length > instanceIDCount) { //If there are more infoboxes than InstanceID parameters per type
if (InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0) { //Display error message for all infoboxes without an InstanceID parameter
wikify("{{Infobox" + TypeX + "Error{\nThere are " + instanceInfoboxTypeResultEmpty.length + " infoboxes of \"" + Type + "\" type, but " + instanceIDCount + " ~IDs. This infobox does not have an ''~InstanceID'' parameter.<br/>When using more than one infobox of the same type, you need to add ''~InstanceID'' parameter to all of them. This parameter can be a random ''alphanumeric'' string and must be different for each infobox of the same type.}}}", place);
return;
}
}
} //End missing check
//Check for duplicate InstanceID parameters for a type
var instanceIDs = [];
var instanceIDMatch;
var n;
if (instanceInfoboxTypeResult.length > 1) { //If there is more than one infobox with the InstanceID parameter
for (n = 0; n < instanceInfoboxTypeResult.length; n++) { //Count the number or InstanceID parameters
if ((instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g) !== null) && !(InstanceID === "DefaultID" || InstanceID === null || InstanceID.length === 0)) {
instanceIDMatch = instanceInfoboxTypeResult[n].match(/InstanceID:"[\w\s]*?"/g);
instanceIDs.push(instanceIDMatch);
}
}
var instanceIDsSorted = instanceIDs.sort();
//var instanceIDsCropped = instanceIDs.replace(/InstanceID:"|"/g, "");
//var instanceIDsSorted = instanceIDsCropped.sort();
//var duplicateIDs = [];
var duplicateIDs = 0;
var o;
for (o = 0; o < instanceIDsSorted.length - 1; o++) { //Find the duplicates
if (instanceIDsSorted[o] === instanceIDsSorted[o+1]) { //DOESN'T PUSH - Perhaps the problem lies in the fact that the array contains InstanceID:"..."" values, which is different type of array, SEE http://www.w3schools.com/js/js_loop_for_in.asp
//duplicateIDs.push(instanceIDsSorted[o]);
duplicateIDs = duplicateIDs +1;
}
}
//alert(duplicateIDs);
/*
var x, y; //Alternative version
for (x = 0; x < instanceIDsSorted.length; x++) { //Find the duplicates
for (y = x + 1; y < instanceIDsSorted.length; y++) {
//alert(instanceIDsSorted[x]+" - "+instanceIDsSorted[y]);
if (instanceIDsSorted[x] === instanceIDsSorted[y]) {
duplicateIDs.push(ps);
}
}
}
*/
if (duplicateIDs > 0) {
wikify("{{Infobox" + TypeX + "Error{\nThis infobox has the same ''~InstanceID'' parameter (\"" + InstanceID + "\") as another infobox of the same type (\"" + Type + "\").<br/>Infoboxes of the same type must have ''unique ~IDs''.}}}", place);
return;
}
} //End duplicate check
} //End of checks when there's more than one instance
//Begin parsing parameters for output
var paramList = store.getTiddlerText("Infobox_"+ Type.replace(/[\s]/g, "_") + "##Content");
var paramListParsed = paramList.replace(/----\n/g, "").replace(/ /g, "_").split("\n"); //Get parameters
var paramCount = 0;
var param;
var k;
for (k = 0; k < paramListParsed.length; k++) {
param = getParam(params, paramListParsed[k], 'unknown');
//Output for section titles
if (paramListParsed[k].indexOf("Section-") !== -1) {
out += "<tr id=\"Section" + TTIX + paramListParsed[k].replace(/Section-|\*\*[\w\W]*?$/g, "") + "\"><td class=\"Infobox" + TypeX + "Subtitle\" colspan=\"4\">" + paramListParsed[k].replace(/Section-|\*\*[\w\W]*?$/g, "").replace(/_/g, " ") + "</td></tr>";
}
//Output for images
else if (paramListParsed[k].indexOf("Image-") !== -1) {
out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/Image-/g, "") + "\"><td class=\"InfoboxCellImage\" colspan=\"4\"><img src=\"" + param + "\" alt=\"" + param + "\" title=\"" + param + "\" class=\"InfoboxImage\"/></td></tr>";
}
//Start output if using sides (left cell)
else if (paramListParsed[k].indexOf("Side1-") !== -1) {
out += "<tr id=\"Content" + TTIX + paramListParsed[k-1].replace(/Section-|\*\*[\w\W]*?$/g, "") + "\"><td class=\"InfoboxCellEqual\" colspan=\"2\">" + param + "</td>";
}
//End output if using sides (right cell)
else if (paramListParsed[k].indexOf("Side2-") !== -1) {
out += "<td class=\"InfoboxCellEqual\" colspan=\"2\">" + param + "</td></tr>";
}
//Normal output
else {
//if ((paramList.indexOf("xSide1-") !== -1) || (paramList.indexOf("xSide2-") !== -1)) { //If parameters contain Side1- or Side2-
//out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/ /g, "") + "\"><td class=\"InfoboxCellEqual\">" + paramListParsed[k].replace(/_/g, " ") + "</td><td class=\"InfoboxCellEqual\">" + param + "</td></tr>";
//}
//else {
out += "<tr id=\"" + TTIX + paramListParsed[k].replace(/ /g, "") + "\"><td class=\"InfoboxCellLeft\">" + paramListParsed[k].replace(/_/g, " ") + "</td><td class=\"InfoboxCellRight\" colspan=\"3\">" + param + "</td></tr>";
//}
}
//Hide lines with no information
if ((param === "unknown") && (paramListParsed[k].indexOf("Section-") === -1)) {
setStylesheet("#" + TTIX + paramListParsed[k].replace(/Image-| /g, "") + " {display: none;}", "Infobox" + TTIX + paramListParsed[k]);
} else {
setStylesheet("#" + TTIX + paramListParsed[k].replace(/Image-| /g, "") + " {display: inherit;}", "Infobox" + TTIX + paramListParsed[k]);
}
//Hide the whole table if all parameters are unknown
if (param === "unknown") { //First count how many params are unknown
paramCount = paramCount + 1;
}
if (paramCount === paramListParsed.length) { //If all params are unknown
setStylesheet("#Table" + TTIX + " {display: none;}\n", "InfoboxTable" + TTIX);
setStylesheet("#NoInfo" + TTIX + " {display: inherit;}", "NoInfo" + TTIX);
} else {
setStylesheet("#Table" + TTIX + " {display: inherit;}\n", "InfoboxTable" + TTIX);
setStylesheet("#NoInfo" + TTIX + " {display: none;}", "NoInfo" + TTIX);
}
} //End parsing of parameters for output
//Hide section title if all params in the section are unknown (requires extra parsing of parameters by sections)
var section = paramList.replace(/Section-[\w\W\n]*?/g, "").replace(/ /g, "_").split("\n----\n"); //Get sections
var sectionParsed, sectionParams;
var sectionParamCount = 0;
var p, q;
if (section.length > 1) {
for (p = 0; p < section.length; p++) {
sectionParsed = section[p].split("\n"); //Split sections into parameters
for (q = 0; q < sectionParsed.length; q++) { //Parse the parameters
sectionParams = getParam(params, sectionParsed[q], 'unknown');
if (sectionParams === "unknown") { //Count how many parameters in the section are unknown
sectionParamCount = sectionParamCount + 1;
}
}
if (sectionParamCount === sectionParsed.length) {
setStylesheet("#Section" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, "") + " {display: none;}", "InfoboxSection" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, ""));
setStylesheet("#Content" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, "") + " {display: none;}", "InfoboxContent" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, ""));
} else {
setStylesheet("#Section" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, "") + " {display: inherit;}", "InfoboxSection" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, ""));
setStylesheet("#Content" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, "") + " {display: inherit;}", "InfoboxContent" + TTIX + sectionParsed[0].replace(/Section-|\*\*[\w\W]*?$/g, ""));
}
sectionParamCount = 0; //Reset the count for the next section
}
}
//Final output
//If NestedSlidersPlugin and HTMLFormattingPlugin are installed and both options are true
if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (version.extensions.HTMLFormattingPlugin && config.options.chkUseHTMLFormattingPlugin === true)) {
wikify(startNSP + out + endNSPHFP, place);
}
//If NestedSlidersPlugin is installed and option is true, HTMLFormattingPlugin is not installed or option is false
else if ((version.extensions.NestedSlidersPlugin && config.options.chkUseNestedSlidersPlugin === true) && (!version.extensions.HTMLFormattingPlugin || config.options.chkUseHTMLFormattingPlugin === false)) {
wikify(startNSP + out + endNSP, place);
}
//If NestedSlidersPlugin and HTMLFormattingPlugin are not installed
else {
wikify(start + out + end, place);
}
}
}; //End of macro
} //End of install only once
//}}}
/***
|Name|[[InfoboxTablesPluginCommand]]|
|Source|http://infoboxes.tiddlyspot.com|
|Documentation|[[InfoboxTablesPluginCommandInfo]]|
|Version|1.0.1|
|Author|Kristjan Brezovnik|
|License|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]<br/>[[ELS Design Studios Legal Statements|http://www.TiddlyTools.com/#LegalStatements]]|
|~CoreVersion|2.6.1|
|Requires|[[InfoboxTablesPlugin]]|
|Type|plugin|
|Description|Provides "infobox info" command for [[InfoboxTablesPlugin]].|
!Configuration
<<option chkInfoboxInfoEditToolbar>> Add/remove ~InfoboxInfo to/from default ~EditToolbar in the default [[ToolbarCommands]] shadow tiddler; requires refresh
<<option chkInfoboxInfoViewToolbar>> Add/remove ~InfoboxInfo to/from default~ViewToolbar in the default [[ToolbarCommands]] shadow tiddler; requires refresh
/***
!Code
***/
//{{{
if(!version.extensions.InfoboxTablesPlugin) { //Check if InfoboxTablesPlugin is installed
throw "InfoboxTablesPlugin is not installed!";
}
else {
//Ensure that the plugin is only installed once
if (!version.extensions.infoboxInfo) {
version.extensions.infoboxInfo = {installed: true};
version.extensions.infoboxInfo = {major: 1, minor: 0, revision: 1, date: new Date(2013,3,27)};
//Stylesheet
var infoStylesheet = store.getTiddler("InfoboxTablesInfoboxInfoStylesheet");
if (infoStylesheet === null) {
config.shadowTiddlers.InfoboxTablesInfoboxInfoStylesheet =
"/***\nStylesheet\n***/\n/*{{{*/\n" +
".InfoboxInfoButton {display: inline-block; position: relative; float: left; clear: both; padding: 1px; margin: 1px; font-size: 10px; line-height: 120%; border: 1px solid black; background: [[InfoboxTablesColorPalette::InfoboxTableBackground]];}\n" +
".InfoboxNoInfo {display: none; width: 300px !important; font-weight: bold; border: solid 2px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px 5px;} /* No Info */\n" +
".InfoboxInfo2, .InfoboxInfo3 {vertical-align: top; font-size: 10px; white-space: nowrap; line-height: 80%; border: 1px solid black !important; border-collapse: collapse;} /* InfoboxInfo tables */\n" +
".InfoboxInfo2 td, .InfoboxInfo3 td, .InfoboxInfo2 th, .InfoboxInfo3 th {border: 1px solid black !important; border-collapse: collapse !important;}\n" +
".InfoboxInfo2 th, .InfoboxInfo3 th {background: darkgrey;}\n" +
".InfoboxInfo2 caption, .InfoboxInfo3 caption {white-space: normal; text-align: left; line-height: 120%;} /* InfoboxInfo captions */\n" +
".InfoboxInfo2 td:last-child {display: none;}\n" +
"/*}}}*/\n";
store.addNotification("InfoboxTablesInfoboxInfoStylesheet", refreshStyles);
}
//Add InfoboxInfo to EditToolbar and ViewToolbar
if (config.options.chkInfoboxInfoEditToolbar === undefined) {
config.options.chkInfoboxInfoEditToolbar = false;
}
if (config.options.chkInfoboxInfoViewToolbar === undefined) {
config.options.chkInfoboxInfoViewToolbar = false;
}
if ((config.options.chkInfoboxInfoEditToolbar === true) && !config.shadowTiddlers.ToolbarCommands.match("EditToolbar\\|infoboxInfo")) {
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.replace(/EditToolbar\|/, "EditToolbar\|infoboxInfo ");
}
if ((config.options.chkInfoboxInfoEditToolbar === false) && config.shadowTiddlers.ToolbarCommands.match("EditToolbar\\|infoboxInfo")) {
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.replace(/EditToolbar\|infoboxInfo /, "EditToolbar|");
}
if ((config.options.chkInfoboxInfoViewToolbar === true) && !config.shadowTiddlers.ToolbarCommands.match("ViewToolbar\\|infoboxInfo")) {
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.replace(/ViewToolbar\|/, "ViewToolbar\|infoboxInfo ");
}
if ((config.options.chkInfoboxInfoViewToolbar === false) && config.shadowTiddlers.ToolbarCommands.match("ViewToolbar\\|infoboxInfo")) {
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.replace(/ViewToolbar\|infoboxInfo /, "ViewToolbar|");
}
//InfoboxInfo command
config.commands.infoboxInfo = {
text: "infobox info",
tooltip: "Show details for infoboxes in the current tiddler"
};
config.commands.infoboxInfo.handler = function(event,src,title) {
config.commands.infoboxInfo.showPopup(src);
};
config.commands.infoboxInfo.showPopup = function(place) { //Show the popup
var tid;
var here = story.findContainingTiddler(place);
if (here) {
tid = store.getTiddler(here.getAttribute("tiddler"));
}
var title = tid.title;
var popupCommand = Popup.create(place);
if (!popupCommand) {
return;
}
addClass(popupCommand,"sticky");
var infoboxInfoDiv = createTiddlyElement(popupCommand, "div", "InfoboxInfoDiv"+title.replace(/[\W\s]/g, ""), "InfoboxOuterDivCommand");
infoboxInfoDiv.style.padding = "5px";
if (tid !== null) { //If the tiddler is not a shadow tiddler
if (tid.isTagged("article") && tid.text.match("infobox")) { //If the tiddler is an article and contains an infobox
var getinfoboxes = store.getTaggedTiddlers("infobox"); //Get all infoboxes
var infoboxarray = "";
var i;
for (i = 0; i < getinfoboxes.length; i++) { //Put the infoboxes into array
infoboxarray += getinfoboxes[i].title.replace(/Infobox_/g, "").replace(/_/g, " ") + ",";
}
var infoboxes = infoboxarray.split(",");
var table = "";
var infoboxcount = 0;
var j;
for (j = 0; j < infoboxes.length; j++) { //Go through all infoboxes
var comms = 0;
if (tid.text.match("Type:\""+infoboxes[j]+"\"")) { //If a tiddler contains an infobox
infoboxcount = infoboxcount + 1;
var info = store.getTiddlerText("Infobox_" + infoboxes[j].replace(/ /g, "_") + "##Content");
var note = store.getTiddlerText("Infobox_" + infoboxes[j].replace(/ /g, "_") + "##Notes");
if (note === undefined) {
note = "";
}
var infosplit = info.replace(/----\n/g, "").split("\n");
var desc, param, comm;
var out = "";
var k;
for (k = 0; k < infosplit.length; k++) { //Parse the infobox
if (infosplit[k].indexOf("Section-") !== -1) {
desc = "|{{Infobox"+infoboxes[j].replace(/ /g, "")+"Title{" + infosplit[k].replace(/Section-/g, "Section: ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "}}}|";
param = "|";
}
else {
desc = "|" + infosplit[k].replace(/Image-/g, "Image: ").replace(/Single-/g, "Single cell: ").replace(/Side1-/g, "Left Side: ").replace(/Side2-/g, "Right Side: ").replace(/ \(\([\w\s]*?\)\)| \*\*[\w\W\s]*?$/g, "") + "|";
if (infosplit[k].indexOf("\(\(") !== -1) {
param = "<nowiki>" + infosplit[k].replace(/^[\w\W\s]*?\(\(|\)\)[\w\W\s]*?$/g, "") + "</nowiki>|";
}
else {
param = "<nowiki>" + infosplit[k].replace(/ \*\*[\w\W\s]*?$/g, "").replace(/ /g, "_") + "</nowiki>|";
}
}
if (infosplit[k].indexOf("\*\*") !== -1) {
comm = infosplit[k].replace(/[\w\W\s]*?\*\*/g, "") + "|\n";
comms = comms + 1;
}
else {
comm = "|\n";
}
out += desc + param + comm;
} //End parse the infobox
if (comms === 0) { //If there are no comments
table += "!" + infoboxes[j] + " \n|!Description|!Parameter|\n"+ out + "|" + note + "|c\n|InfoboxInfo2|k\nsplitter" + infoboxes[j] + "splitter";
}
else { //If there are comments
table += "!" + infoboxes[j] + "\n|!Description|!Parameter|!Comment|\n"+ out + "|" + note + "|c\n|InfoboxInfo3|k\nsplitter" + infoboxes[j] + "splitter";
}
} //End if a tiddler contains the infobox
} //End go through all infoboxes
var tableSplit = table.split("splitter");
tableSplit.pop();
if (infoboxcount === 1) { //If there is only one infobox type, display the content
wikify("{{SmallText{This article contains the following infobox:}}}\n" + table.replace(/splitter[\w\W\s]+?splitter/g, ""), infoboxInfoDiv);
}
else { //If there are more infobox types, show a list
wikify("{{SmallText{This article contains the following infoboxes:}}}\n",infoboxInfoDiv);
var ButtonTitleSub;
var ButtonTooltipSub;
var x;
for (x = 0; x < tableSplit.length; x = x + 2) {
ButtonTitleSub = tableSplit[x+1];
ButtonTooltipSub = tableSplit[x+1];
var infoboxInfoButtonSub = createTiddlyButton(infoboxInfoDiv, ButtonTitleSub, ButtonTooltipSub, function() {config.commands.infoboxInfo.toggleInfoboxInfo(this.nextSibling,this);}, "InfoboxInfoButton", "InfoboxInfoButton"+tableSplit[x+1].replace(/ /g, ""));
infoboxInfoButtonSub.setAttribute("closedtext",ButtonTitleSub);
infoboxInfoButtonSub.setAttribute("closedtip",ButtonTooltipSub);
infoboxInfoButtonSub.setAttribute("openedtext",ButtonTitleSub);
infoboxInfoButtonSub.setAttribute("openedtip",ButtonTooltipSub);
var infoboxInfoDivSub = createTiddlyElement(infoboxInfoDiv, "div", "InfoboxInfoDivSub"+title.replace(/[\W\s]/g, "")+tableSplit[x+1].replace(/[\W\s]/g, ""), "InfoboxInnerDivCommand");
infoboxInfoDivSub.style.display = "none";
wikify(tableSplit[x], infoboxInfoDivSub);
}
}
} //End if the tiddler is an article and contains an infobox
else {
wikify("The tiddler is not an article.", infoboxInfoDiv);
}
} //End if the tiddler is not a shadow tiddler
Popup.show();
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
return false;
}
}; //End show the popup
//Get content panel index
config.commands.infoboxInfo.panelIndex = function(panel) {
var panelIndex = 0;
while((panel = panel.previousSibling) !== null) {
panelIndex++;
}
return panelIndex;
};
//End get content panel index
//Toggle display of infoboxInfo popup
config.commands.infoboxInfo.toggleInfoboxInfo = function(panel,button) {
var panelIndex = config.commands.infoboxInfo.panelIndex(panel);
var i;
var siblings = panel.parentNode.childNodes.length;
for(i = 0; i < siblings; i++) {
if(i !== panelIndex) {
panel.parentNode.childNodes.item(i).style.display = "none";
}
}
if (panel.style.display === "none") {
panel.style.display = "block";
button.innerHTML = button.getAttribute("openedtext");
button.setAttribute("title",button.getAttribute("openedtip"));
if (window.adjustPopupPosition && panel.parentNode.parentNode.id === "popup") {
window.adjustPopupPosition(panel.parentNode.parentNode,button,panel);
}
} else {
panel.style.display = "none";
button.innerHTML = button.getAttribute("closedtext");
button.setAttribute("title",button.getAttribute("closedtip"));
//if (window.adjustPopupPosition && panel.parentNode.parentNode.id === "popup") {
//window.adjustPopupPosition(panel.parentNode.parentNode,button,panel);
//}
}
};
//End toggle display of infoboxInfo popup
//Modified from StickyPopupPlugin (http://www.TiddlyTools.com/#StickyPopupPlugin)
//ELS Design Studios Legal Statements (http://www.TiddlyTools.com/#LegalStatements) apply
//This was added to avoid having to install the StickyPopupPlugin
Popup.stickyPopupCommand = function(event) {
var e = event ? event : window.event;
var target = resolveTarget(e);
var pop = target;
while (pop) { //If in a sticky popup
if (hasClass(pop,"popup") && hasClass(pop,"sticky")) {
break;
}
else {
pop = pop.parentNode;
}
}
if (!pop) { //If not in sticky popup
Popup.onDocumentClick(event);
return true;
}
};
try {
removeEvent(document,"click",Popup.onDocumentClick);
}
catch(e) {}
try {
addEvent(document,"click",Popup.stickyPopupCommand);
}
catch(e) {}
//End modified from StickyPopupPlugin (http://www.TiddlyTools.com/#StickyPopupPlugin)
//Adjust the popup position for when there is more than one infobox type
if (window.adjustPopupPosition === undefined) {
window.adjustPopupPosition = function (place,button,panel) {
if (hasClass(panel, "InfoboxInnerDivCommand")) {
var rightEdge = document.body.offsetWidth - 1;
var panelWidth = place.offsetWidth;
//var left = 1442;
var left = 0;
if (findPosX(place) + panelWidth > rightEdge) {
left = rightEdge - panelWidth;
}
place.style.left = left + "px";
}
};
}
//End adjust the popup position for when there is more than one infobox type
} //End of install only once
}
//}}}
/***
|Name|[[InfoboxTablesPluginCommand]]|
|Source|http://infoboxes.tiddlyspot.com|
|Documentation|[[InfoboxTablesPluginCommandInfo]]|
|Version|1.0.1|
|Author|Kristjan Brezovnik|
|License|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]<br/>[[ELS Design Studios Legal Statements|http://www.TiddlyTools.com/#LegalStatements]]|
|~CoreVersion|2.6.1|
|Requires|[[InfoboxTablesPlugin]]|
|Type|plugin|
|Description|Provides "infobox info" command for [[InfoboxTablesPlugin]].|
!Notes
This used to be a part of [[InfoboxTablesPlugin]] to help when figuring out which parameters to use. But since [[InfoboxTablesPlugin]] has an in-place edit mode as of version 2.2.0, this command is no longer necessary. It can, however still be used for informational purposes.
!Use
!Configuration
<<option chkInfoboxInfoEditToolbar>> Add/remove ~InfoboxInfo to/from default ~EditToolbar in the default [[ToolbarCommands]] shadow tiddler; requires refresh
<<option chkInfoboxInfoViewToolbar>> Add/remove ~InfoboxInfo to/from default~ViewToolbar in the default [[ToolbarCommands]] shadow tiddler; requires refresh
!!~InfoboxInfo Command (infoboxInfo)
The plugin also defines the ''infoboxInfo'' command. This command is not mandatory for displaying the actual infoboxes, however, it does enable you to view the infobox template in a dropdown menu, so you can quickly see which parameters are supported (and copy them), whether there are shorthand parameters, as well as any comments and notes. Under Configuration, you can quickly add it to the default ~EditToolbar or ~ViewToolbar slice in [[ToolbarCommands]]. However, note that this solution uses cookies, so if you enable it in one browser, it won't work in any other browser, unless you also enable it in the other browser. And if you clear the cookies on browser close, you need to re-enable the option manually, unless you use a plugin for saving ~TiddlyWiki cookies.
You can also permanently enable the options by putting the following in a tiddler tagged ''systemConfig'':
{{{
config.options.chkInfoboxInfoEditToolbar=true;
config.options.chkInfoboxInfoViewToolbar=true;
}}}
If you use the SystemSettings tiddler, you need to add:
{{{
chkInfoboxInfoEditToolbar: true
chkInfoboxInfoViewToolbar: true
}}}
If you use your own toolbars or if you modified the existing ~EditToolbar or ~ViewToolbar slice in the [[ToolbarCommands]], you need to add the command manually.
Example for [[ToolbarCommands]]:
{{{
|ViewToolbar|infoboxInfo ...|
|EditToolbar|infoboxInfo ...|
}}}
Example for modified EditTemplate and ViewTemplate:
{{{
<div class='toolbar' macro='toolbar infoboxInfo ...'></div>
}}}
Adding it to the ~ViewToolbar is useful if you use [[EditSectionPlugin|http://www.TiddlyTools.com/#EditSectionPlugin]].
After you add the infoboxInfo command to a template or toolbar, in order for the dropdown menu to actually show up, the ''tiddler must be tagged'' with the tag ''article'' and a ''valid Type in lower case'', as well as actually contain an infobox with a valid type. Also, you must save/create the tiddler before you can use this command.
!!Shadow tiddlers
In the [[InfoboxTablesColorPalette]] shadow tiddler you can modify the color scheme without modifying the templates.
In the [[InfoboxTablesStylesheet]] shadow tiddler you can modify the layout a bit.
!Version History
1.0.1 - Added check to see if InfoboxTablesPlugin is installed
1.0.0 - Initial standalone release (from InfoboxTablesInfobox 2.1.1)
>Added separate [[InfoboxTablesPluginCommand|info]] tiddler
|Name|[[InfoboxTablesPlugin]]|
|Source|http://infoboxes.tiddlyspot.com|
|Documentation|[[InfoboxTablesPluginInfo]]|
|Version|2.2.2|
|Author|Kristjan Brezovnik|
|License|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|~CoreVersion|2.6.3|
|Requires||
|Type|plugin|
|Description|Provides customizable infoboxes for different types of articles.|
!Notes
This plugin is intended to simulate the Wookiepedia/Wikipedia style infoboxes. If you're a writer, you need to keep a list of characters and events, and with ~TiddlyWiki you can make a simple wiki to help you do that. These infoboxes help you list basic information in an easy and clear way. It is designed to be generic, so you can define your own types of infoboxes or modify the ones I've made.
In ~TiddlyWiki 2.6.2 and probably earlier, Internet Explorer didn't hide the whole table correctly, if there were no information, and there might have been some other related minor issues. ~TiddlyWiki 2.6.3 seems to have corrected that.
!Use
!!Configuration
<<option chkHideInfoboxes>> Hide the infoboxes when opening a tiddler
<<option chkSaveMode>> When editing the table, save the macro so each parameter is in its own line (default) or so that the entire macro is a single line
<<option chkSavePrompt>> Prompt if you really want to save
!!~InfoboxInfo Command (infoboxInfo)
No longer necessary as of InfoboxTablesPlugin version 2.2.0. It is still available as a dependent plugin ([[InfoboxTablesInfoboxInfoCommand]]) with accompanying information ([[InfoboxTablesInfoboxInfoCommandInfo]]).
!!Infobox Macro (infobox)
Use:
{{{
<<infobox Type:"value" Title:"value" InstanceID:"value" parameter_name:"value" parameter_name:"value" parameter_name:"value" ... parameter_name:"value">>
}}}
There are three predefined parameters, of which one is mandatory (Type) and two are optional (Title and ~InstanceID).
The only mandatory parameter is ''Type'', because it determines which template will be used.
For parameter values, you need to use HTML code to add styling, not wiki markup. You can use line breaks, but they get eaten, if you don't use the <br/> tag. If you use HTML tags that already add a line break, like <li></li>, you don't need to add <br/> afterwards.
Normally, you use one infobox of a type in a tiddler. If, however, that is not enough, you can use the ''~InstanceID'' parameter and assign ''each'' instance a ''unique ID''. Note that if using more than one instance of the same type, you ''must'' use the ''~InstanceID'' parameter for all of them, otherwise the settings from the last one used override the settings from the ones before. If you use instances of different types or if you only use one instance, the ''~InstanceID'' parameter is not required. The plugin also checks for missing or duplicate ''~InstanceID'' parameters.
By default, the tiddler title is displayed in the table header, since the subject of the tiddler is usually also the subject of the table. You can, however, define a custom title using the ''Title'' parameter, which is useful when you have multiple infoboxes in the same tiddler.
The order in which the parameters will be displayed in a table is defined in the template. Because this plugin uses named parameters, you can list them in any order in the macro and they will be displayed correctly. However, due to an easier overview, I suggest you stick to the order in the template.
Because there are often many parameters, you can write each parameter on its own line, so you have a better overview. This is how the edit mode saves them by default. You can, however, also use the option above to specify that you want the edit mode to write the entire macro as a single line.
!!Edit Mode
Edit mode enables you to edit the infobox without having to open the tiddler and manually enter parameters. The only parameter that you need to enter is Type. If you use multiple infoboxes of the same type in the same tiddler, you also need to enter ~InstanceID. After that, you can use edit mode to add the rest of the parameters.
All parameters specified in the template are available in edit mode. Any comments are visible above the respective text area where you enter the values. If the value is empty or unknown, the macro ignores those parameters when saving.
Note that if you change the template, ie add, remove or rename a parameter, the newly added or the renamed parameters will show up in edit mode, but the old ones won't. So if you need the information from the old or renamed parameter, you need to backup the data, because once you save the infobox from edit mode, the old macro will be overwritten.
Edit mode is ''not'' supported for error messages. In this case you need to edit the macro manually. You only need to correct/add the Type and/or ~InstanceID parameter. Once they're correct, you can use the edit mode normally.
You can cancel editing an infobox by pressing escape, but only as long as you're somewhere on the infobox. If you click in the tiddler or somewhere else off the infobox, escape won't work. This is to prevent the escape key from affecting other potential infoboxes in the same tiddler.
Cancelling edit resets the edit mode and you will lose any changes.
You can also delete the infobox from the tiddler.
!!Error messages
An error message is displayed in the following cases:
*if you enter a wrong type
*if you don't enter the type
*if you use multiple infoboxes of the same type and you forget to add the ~InstanceID parameters to all of them
*if you use multiple infoboxes of the same type and you use a duplicate ~InstanceID parameter
!!Shadow tiddlers
In the [[InfoboxTablesColorPalette]] shadow tiddler you can modify the color scheme without modifying the templates.
In the [[InfoboxTablesStylesheet]] shadow tiddler you can modify the layout a bit.
!!Templates
You can define your own templates, which should be named ''Infobox_<Type>'' and tagged ''infobox''. Replace <Type> to match whatever information the infobox will display. Note that you should ''use underscores instead of spaces''.
Templates consists of two mandatory sections (Content and Colors) and one optional (Notes).
Under ''Content'', you can specify how the table will be set up and what parameters are supported.
Under ''Colors'', you can specify the color of the table header/footer (Title) and section titles (Subtitle). The basic table colors can be changed in the [[InfoboxTablesColorPalette]] shadow tiddler.
Under ''Notes'', you can write any information you might think is relevant to the template.
Each table section consists of a table title and the group of relevant parameters. Note that images can also be a part of a section or they can be in a section of their own.
Table sections are separated with the four dashes separator.
There are several key words that help with table formatting:
*''Section-'' - denotes a section title
*''Image-'' - denotes an image
*''Side1-'' - denotes the left side of a comparison
*''Side2-'' - denotes the right side of a comparison
*''((...))'' - denotes a shorthand parameter; must follow a normal parameter (it is irrelevant for section titles)
*''**'' - denotes a comment; must follow the shorthand parameter, if any, or the parameter
Order:
Descriptive parameter ((shorthand)) **Comment
Section-, Image-, Side1- and Side2- all contain a mandatory dash, which cannot be followed by a space.
Side1- and Side2- should be in a section by themselves.
The shorthand parameters must be separated with a space from the descriptive parameter.
Comments must be separated with a space from the parameter/shorthand parameter. They are not visible in the table.
Parameters may contain spaces in the template, but these ''spaces must be replaced with underscores when used in the macro''. There is no limitation on the number of parameters or sections, but, the more parameters there are, the longer the table takes to render.
If a parameter does not have a value, the line is hidden. If all parameters in a section are unknown, the whole section is hidden. If all parameters in the table is unknown, the whole table is hidden.
Usually, you write out parameters descriptively, since they are displayed in the left table column. Shorthand parameters can be used to help you shorten the amount of text you need to write. Note that if you define a shorthand parameter, you need to use it instead of the descriptive parameter. In the table, only the descriptive parameters are displayed. If you assign a shorthand parameter to a parameter that uses a key word, you don't need to include the keyword in the shorthand parameter. Sections don't take shorthand parameters and if you add one, it will be removed.
Sections don't take shorthand parameters, so if you mistakenly add one, it will automatically be removed.
Comments are usuful for adding specifics regarding a parameter or a section.
After adding a new template or modifying an existing one, you might need to refresh.
!!!Template structure
!Content
~Image-Your image 1
----
~Section-Section 1 title **Optional comment for section
Section 1 param 1
Section 1 param 2
Section 1 param n
----
~Image-Your image 2
----
~Section-Section 2 title **Optional comment for section
Section 2 param 1
~Image-Your image 3 **Optional comment for a param without a shorthand param
Section 2 param 2 ((random)) **Optional comment for a param with a shorthand param
Section 2 param n
----
~Section-Section 3 title **Optional comment for section
~Side1-Section 3 param 1 ((left)) **Notice how the keyword is not included in the shorthand parameter
~Side2-Section 3 param 2 ((right))
----
~Section-Section n title
Section n param 1
Section n param 2
Section n param n
!Colors
Text:black
Title:green
Subtitle:yellow
!Notes
Here you can add a detailed description or some other note.
!!!Bare minimum template
!Content
!Colors
Text:
Title:
Subtitle:
!!!Sample templates used in examples
* [[Infobox_Example_Battle]]
* [[Infobox_Example_Person]]
!Downlodable templates
Note that you can modify these templates and adapt them to your own needs. You don't need to download them, if you don't need them. You can, of course, also create new ones.
<<list filter "[tag[infobox]]">>
!Examples
<<list filter [tag[infoboxexample]]>>
!Version History
2.2.2 - Fixed a conflict with [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]], which added extra span tags, which is why the HTML code wasn't correctly cleaned up in inline edit mode
2.2.1 - Minor code cleanup and CSS fix to enforce button style
2.2.0 - Added in-place edit for infoboxes (including for error messages), which also includes the ability to delete the infobox
>moved InfoboxInfo command to a separate dependent plugin ([[InfoboxTablesInfoboxInfoCommand]]) (not required anymore, but can still be used)
>added check, if InfoboxTablesColorPalette and InfoboxTablesStylesheet exist, skip creating shadow tiddlers
>fixed a bug where an error was reported, if there were two templates and one template contained the other's name (ie Template_Officer and Template_Navy_Officer or Template_Vessel and Template_Vessel_Class; the "Template_" part is removed during processing; the template names are used as the Type parameter) and they both had the same ~InstanceID parameter
>fixed a bug where comments sometimes caused problems with displaying parameters
>added check for illegal shorthand parameters in section titles
>added more information
>optimized the code a little
2.1.1 - Fixed the issue where the error messages were incorrectly placed; removed the requirement that the tiddlers be tagged with infobox type
2.1.0 - Turned infoboxInfo a proper command (checkboxes now add to the ToolbarCommands slices instead of ViewTemplate and EditTemplate)
>removed dependency on NestedSlidersPlugin for both the Infobox and ~InfoboxInfo macros
>cleaned up the stylesheet some more
>fixed the table lines in the popup infoboxInfo tables
>added formatting to the color palette and stylesheet; made the button for the infobox table panel in the body dynamic
2.0.7 - Fixed a bug in InfoboxInfo, where the wrong matching function broke the macro; tweaked the stylesheet to make the tables more compact; changed the code that still depended on the [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]]
2.0.6 - Minor code cleanup and documentation update
2.0.5 - Added the option to show the infobox tables hidden
>removed the need for the [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]]
>remove the need for [[CoreTweaks|http://www.TiddlyTools.com/#CoreTweaks]] if core version is less than 2.6.3
>replaced the "Show info" button with a link to the infobox template
>added the ~InfoboxInfo function
>removed the InfoboxTablesInfo shadow tiddler, since it was replaced with a link to the template and the ~InfoboxInfo function
>tweaked the stylesheet some more
>made the title non-wikified, so came case words don't become wiki links
2.0.1 - Fixed the table styling bug by changing the output so that each section is a separate table and all the tables are contained in a div container; fixed a bug where the sections didn't hide correctly if all params were unknown; cleaned up the stylesheet; added support for comments anywhere in the Content section
2.0.0 - Completely rewrote the plugin to make it generic, reduce the number of lines and macros and to enable easier adding of infobox templates
>removed the dependency on [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] and [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]] (although it can still make use of them, if they're present; added option to disable using these two plugins even if they're installed)
>rewrote the documentation and put it in a separate tiddler
>added templates, which were previously part of the macro
>added examples of use
>added support for images, comments for sections and template comments
>removed the scripts checking if third party plugins exist (the macro checks that and modifies the output accordingly)
>enabled multiple instances of the same type in the same tiddler using ~InstanceID parameter (including check of missing or duplicate ~InstanceID parameters)
>added the option to use Title parameter to give the infobox a custom name (for example when using multiple instances or in case you don't want the title to be the tiddler title)
>added the ability to define "shorthand" parameters, which can be used instead of the long descriptive parameters
>removed ~InfoboxInfo
1.2.7 - Added ~IDs to table rows and the CSS class names, so that they are differentiated by tiddler names and don't mess things up between tiddlers
1.2.6 - Moved macro-specific styles to their respective macros, thereby enabling modularity (moving individual infoboxes to their own tiddlers); renamed Vehicle to Vehicle Class and Fighter to Fighter Class
1.2.5 - Changed from unnamed parameters to named parameters
1.2.2 - Replaced the button for checking if [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] exists with a script; added ~InfoboxInfo (requires [[ForEachTiddlerPlugin|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin]])
1.2.1 - Moved [info] button content display to a nested slider instead of an annotation; moved the info content itself to a shadow tiddler; added a button to check if [[NestedSlidersPlugin|http://www.TiddlyTools.com/#NestedSlidersPlugin]] is installed
1.2.0 - Added shadow tiddlers for color palette and stylesheet to enable easier modifying of the infobox color scheme; moved everything style-related to stylesheet
1.1.2 - Renamed from ~InfoboxMacrosPlugin to ~InfoboxTablesPlugin; added the [info] button with information on what information can be entered; modified some parameters
1.1.1 - Included the stylesheet into the plugin itself; added documentation
1.1.0 - Added rounded corners and styles instead of direct code; added formatting to the code for easier understanding and to give it a plugin look
1.0.1 - Changed code so it automatically includes the tiddler title
1.0.0 - Initial version
!Content
Image-Battle
----
Section-Conflict
Date
Place
Outcome
Previous
Concurrent
Next
----
Section-Combatants
Side1-Good combatants
Side2-Bad combatants
----
Section-Commanders
Side1-Good commanders
Side2-Bad commanders
----
Section-Strength
Side1-Good strength
Side2-Bad strength
----
Section-Casualties
Side1-Good casualties
Side2-Bad casualties
!Colors
Text:
Title:crimson
Subtitle:red
!Notes
This is template is based on the Battle template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-City
----
Section-General information
Constructed
Location information
Planet
Location
----
Section-Societal
Eras
Affiliation
!Colors
Text:
Title:palegoldenrod
Subtitle:lemonchiffon
!Notes
This is template is based on the City template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Company
----
Section-Organizational information
Primary roles
Chronological and political information
Eras
!Colors
Text:
Title:slategray
Subtitle:lightslategray
!Notes
This is template is based on the Company template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Country
----
Section-Physical
Planet
Location
Climate
Primary terrain
Points of interest
----
Section-Societal
Native species
Immigrated species
Official language
Population
Major cities
Major imports
Major exports
Affiliation
!Colors
Text:
Title:orange
Subtitle:sandybrown
!Notes
This is template is based on the Country template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Creature
Designation
Planet of origin
Height of average adult
Skin color
Distinctions
!Colors
Text:
Title:darkturquoise
Subtitle:whitesmoke
!Notes
This is template is based on the Creature template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Droid
----
Section-Production information
Homeworld
Date created
Creator
Manufacturer
Model
Class
----
Section-Technical specifications
Height
Gender
Sensor color
Armament
Equipment
----
Section-Chronological and political information
Eras
Affiliation
!Colors
Text:
Title:silver
Subtitle:lightgray
!Notes
This is template is based on the Droid template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Event
Date
Place
Affiliations involved
Participants
!Colors
Text:
Title:deeppink
Subtitle:whitesmoke
!Notes
This is template is based on the Event template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Battle ((img)) **You can add a comment anywhere
----
Section-Conflict **To section titles
Date **Or to data
Place ((loc))
Outcome
Previous
Concurrent
Next
----
Section-Combatants **Notice, how this and the following three sections only contain two parameters each
Side1-Good combatants ((gfighters))
Side2-Bad combatants ((bfighters))
----
Section-Commanders **Notice the "shorthand" parameters
Side1-Good commanders ((gcommanders))
Side2-Bad commanders ((bcommanders))
----
Section-Strength **While shorthand parameters may contain spaces, their purpose is to be short
Side1-Good strength ((gstrength))
Side2-Bad strength ((bstrength))
----
Section-Casualties **All parameters may contain spaces
Side1-Good casualties
Side2-Bad casualties
!Colors
Text:
Title:crimson
Subtitle:red
!Notes
This is a modified Battle template, which is used for demonstration purposes. For actual use, use the [[Battle|Infobox_Battle]] template instead.
!Content
Image-Person **Notice how the image is all alone and not in a section
----
Section-Biographical information
Homeworld
Born
Died
----
Section-Physical description **Notice how there is no space between the keyword's dash and the parameter name
Species
Gender
Height
Hair color
Eye color
Skin color
----
Section-Chronological and political information **Notice the space between the parameter name and the comment separator
Eras
Affiliation
Known masters
Known apprentices
!Colors
Text:white
Title:mediumblue
Subtitle:blue
!Notes
This is a modified Person template, which is used for demonstration purposes. For actual use, use the [[Person|Infobox_Person]] template instead.
!Content
Image-Fighter Class
----
Section-Production information
Manufacturer
Model
Class
Cost
----
Section-Technical specifications
Length
Maximum acceleration
MGLT
Maximum speed (atmosphere)
Engine units
Alternate configuration
Hyperdrive rating
Hyperdrive system
Power plant
Shielding
Hull
Sensor systems
Targeting systems
Navigation system
Avionics
Countermeasures
Armament
Crew
Passengers
Cargo capacity
Consumables
Other systems
----
Section-Usage
Roles
Eras
Affiliation
!Colors
Text:
Title:bisque
Subtitle:papayawhip
!Notes
This is template is based on the Fighter Class template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Location
----
Section-General information
Location
Builder
----
Section-Usage
Eras
Affiliation
!Colors
Text:
Title:peru
Subtitle:burlywood
!Notes
This is template is based on the Location template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Organization
----
Section-General information
Leaders
Notable members
Headquarters
Locations
----
Section-Historical information
Fragmentation
Reorganization
Dissolution
Restoration
----
Section-Other information
Eras
Affiliation
!Colors
Text:
Title:darkslategray
Subtitle:dimgray
!Notes
This is template is based on the Organization template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Person
----
Section-Biographical information
Homeworld
Born
Died
----
Section-Physical description
Species
Gender
Height
Hair color
Eye color
Skin color
----
Section-Chronological and political information
Eras
Affiliation
Known masters
Known apprentices
!Colors
Text:
Title:mediumblue
Subtitle:blue
!Notes
This is template is based on the Person template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Planet
----
Section-Astrographical
Region
System
Suns
Moons
Rotation period
Orbital period
----
Section-Physical
Class
Diameter
Atmosphere
Climate
Gravity
Primary terrain
Points of interest
----
Section-Societal
Native species
Immigrated species
Official language
Population
Major cities
Major imports
Major exports
Affiliation
!Colors
Text:
Title:darkgoldenrod
Subtitle:goldenrod
!Notes
This is template is based on the Planet template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Plant
Planet of origin
Distinctions
!Colors
Text:
Title:dodgerblue
Subtitle:whitesmoke
!Notes
This is template is based on the Plant template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Species
Homeworld
Language
Average height
Hair color
Skin color
Distinctions
Races
Average lifespan
Famous members
!Colors
Text:
Title:midnightblue
Subtitle:
!Notes
This is template is based on the Species template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-System
----
Section-Astrographical
Region
System
Suns
Planets
Moons
Asteroids
Affiliation
!Colors
Text:
Title:gold
Subtitle:yellow
!Notes
This is template is based on the System template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Tool
!Colors
Text:
Title:silver
Subtitle:gainsboro
!Notes
This is template is based on the Tool template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Vehicle
----
Section-Production information
Manufacturer
Product line
Model
Class
Cost
----
Section-Technical specifications
Length
Height/depth
Maximum speed
Maximum altitude
Engine units
Armament
Crew
Passengers
Cargo capacity
----
Section-Usage
Roles
Eras
Affiliation
!Colors
Text:
Title:tan
Subtitle:wheat
!Notes
This is template is based on the Vehicle Class template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Vessel
Class
Year launched
Notable crew
Special characteristics
Participation at important events
Eras
Affiliation
!Colors
Text:
Title:navajowhite
Subtitle:peachpuff
!Notes
This is template is based on the Vessel template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Vessel Class
----
Section-Production information
Manufacturer
Product line
Model
Class
Cost
----
Section-Technical specifications
Length
Maximum acceleration
MGLT
Engine units
Hyperdrive rating
Hyperdrive system
Power output
Power plant
Shielding
Sensor systems
Targeting systems
Armament
Complement
Crew
Minimum crew
Passengers
Cargo capacity
Consumables
Other systems
----
Section-Usage
Roles
Year introduced
Eras
Affiliation
!Colors
Text:
Title:navajowhite
Subtitle:peachpuff
!Notes
This is template is based on the Vessel_Class template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-War
----
Section-General
Beginning
End
Place
Outcome
Major battles
----
Section-Combatants
Side1-Good combatants
Side2-Bad combatants
----
Section-Commanders
Side1-Good commanders
Side2-Bad commanders
!Colors
Text:
Title:darkred
Subtitle:firebrick
!Notes
This is template is based on the War template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
!Content
Image-Weapon
!Colors
Text:
Title:grey
Subtitle:darkgrey
!Notes
This is template is based on the Weapon template from the [[Wookipedia|http://starwars.wikia.com/wiki/Main_Page]].
version.extensions.InstantTimestamp = { major: 1, minor: 0, revision: 4, date: new Date(2006,4,6),
source: "http://simonbaird.com/mptw/#InstantTimestamp"
};
config.InstantTimestamp = {
timeFormat: 'DD/0MM/YY 0hh:0mm',
dateFormat: 'DD/0MM/YY',
translations: [
[/^!ts?$/img, "'!!'+now.formatString(config.InstantTimestamp.timeFormat)"],
[/^!ds?$/img, "'!!'+now.formatString(config.InstantTimestamp.dateFormat)"],
[/\{ts?\}/ig, "now.formatString(config.InstantTimestamp.timeFormat)"],
[/\{ds?\}/ig, "now.formatString(config.InstantTimestamp.dateFormat)"]
],
excludeTags: [
"noAutoCorrect",
"CSS",
"css",
"systemConfig",
"zsystemConfig",
"Plugins",
"Plugin",
"plugins",
"plugin",
"javascript",
"code"
],
excludeTiddlers: [
"StyleSheet",
"StyleSheetLayout",
"StyleSheetColors",
"StyleSheetPrint"
]
};
if (!Array.prototype.contains)
Array.prototype.contains = function(item) {
return (this.find(item) != null);
};
if (!Array.prototype.containsAny)
Array.prototype.containsAny = function(items) {
for (var i=0;i<items.length;i++)
if (this.contains(items[i]))
return true;
return false;
};
TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags) {
tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
var conf = config.InstantTimestamp;
if ( !tags.containsAny(conf.excludeTags)
&& !conf.excludeTiddlers.contains(newTitle) ) {
var now = new Date();
var trans = config.InstantTimestamp.translations;
for (var i=0;i<trans.length;i++) {
newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
}
}
return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags);
}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''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|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
[[GettingStarted]]
¦
[[Wiki Formatting]]
[[Wiki Link Formatting]]
¦
''<html><a style="color:white"
href="javascript:void(0)"
onclick="story.closeAllTiddlers();story.displayTiddlers(null,store.getTiddlerText('DefaultTiddlers').readBracketedList())"
>Home</a></html>''
¦
[[Copyright]]
¦
@@color:white;Last updated on <<date filedate "DDD, MMM DDth, YYYY at 0hh:0mm:0ss">>@@
/***
|''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"
});
*/
//}}}
/***
|Requires|ShCore.js|
***/
//{{{
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function getKeywordsCSS(str)
{
return '\\b([a-z_]|)' + str.replace(/ /g, '(?=:)\\b|\\b([a-z_\\*]|\\*|)') + '(?=:)\\b';
};
function getValuesCSS(str)
{
return '\\b' + str.replace(/ /g, '(?!-)(?!:)\\b|\\b()') + '\:\\b';
};
var keywords = 'ascent azimuth background-attachment background-color background-image background-position ' +
'background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top ' +
'border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color ' +
'border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width ' +
'border-bottom-width border-left-width border-width border bottom cap-height caption-side centerline clear clip color ' +
'content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display ' +
'elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font ' +
'height left letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top ' +
'margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans ' +
'outline-color outline-style outline-width outline overflow padding-top padding-right padding-bottom padding-left padding page ' +
'page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position ' +
'quotes right richness size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress ' +
'table-layout text-align top text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em ' +
'vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index';
var values = 'above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder '+
'both bottom braille capitalize caption center center-left center-right circle close-quote code collapse compact condensed '+
'continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double '+
'embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia '+
'gray green groove handheld hebrew help hidden hide high higher icon inline-table inline inset inside invert italic '+
'justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha '+
'lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower '+
'navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset '+
'outside overline pointer portrait pre print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side '+
'rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow '+
'small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize '+
'table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal '+
'text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin '+
'upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow';
var fonts = '[mM]onospace [tT]ahoma [vV]erdana [aA]rial [hH]elvetica [sS]ans-serif [sS]erif [cC]ourier mono sans serif';
this.regexList = [
{ regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // double quoted strings
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // single quoted strings
{ regex: /\#[a-fA-F0-9]{3,6}/g, css: 'value' }, // html colors
{ regex: /(-?\d+)(\.\d+)?(px|em|pt|\:|\%|)/g, css: 'value' }, // sizes
{ regex: /!important/g, css: 'color3' }, // !important
{ regex: new RegExp(getKeywordsCSS(keywords), 'gm'), css: 'keyword' }, // keywords
{ regex: new RegExp(getValuesCSS(values), 'g'), css: 'value' }, // values
{ regex: new RegExp(this.getKeywords(fonts), 'g'), css: 'color1' } // fonts
];
this.forHtmlScript({
left: /(<|<)\s*style.*?(>|>)/gi,
right: /(<|<)\/\s*style\s*(>|>)/gi
});
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['css'];
SyntaxHighlighter.brushes.CSS = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
//}}}
/***
***/
/*{{{*/
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
var keywords = 'break case catch continue ' +
'default delete do else false ' +
'for function if in instanceof ' +
'new null return super switch ' +
'this throw true try typeof var while with'
;
var r = SyntaxHighlighter.regexLib;
this.regexList = [
{ regex: r.multiLineDoubleQuotedString, css: 'string' }, // double quoted strings
{ regex: r.multiLineSingleQuotedString, css: 'string' }, // single quoted strings
{ regex: r.singleLineCComments, css: 'comments' }, // one line comments
{ regex: r.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: /\s*#.*/gm, css: 'preprocessor' }, // preprocessor tags like #region and #endregion
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keywords
];
this.forHtmlScript(r.scriptScriptTags);
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['js', 'jscript', 'javascript'];
SyntaxHighlighter.brushes.JScript = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
/*}}}*/
//{{{
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['text', 'plain'];
SyntaxHighlighter.brushes.Plain = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
//}}}
//{{{
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
// Contributed by Gheorghe Milas and Ahmad Sherif
var keywords = 'and assert break class continue def del elif else ' +
'except exec finally for from global if import in is ' +
'lambda not or pass print raise return try yield while';
var funcs = '__import__ abs all any apply basestring bin bool buffer callable ' +
'chr classmethod cmp coerce compile complex delattr dict dir ' +
'divmod enumerate eval execfile file filter float format frozenset ' +
'getattr globals hasattr hash help hex id input int intern ' +
'isinstance issubclass iter len list locals long map max min next ' +
'object oct open ord pow print property range raw_input reduce ' +
'reload repr reversed round set setattr slice sorted staticmethod ' +
'str sum super tuple type type unichr unicode vars xrange zip';
var special = 'None True False self cls class_';
this.regexList = [
{ regex: SyntaxHighlighter.regexLib.singleLinePerlComments, css: 'comments' },
{ regex: /^\s*@\w+/gm, css: 'decorator' },
{ regex: /(['\"]{3})([^\1])*?\1/gm, css: 'comments' },
{ regex: /"(?!")(?:\.|\\\"|[^\""\n])*"/gm, css: 'string' },
{ regex: /'(?!')(?:\.|(\\\')|[^\''\n])*'/gm, css: 'string' },
{ regex: /\+|\-|\*|\/|\%|=|==/gm, css: 'keyword' },
{ regex: /\b\d+\.?\w*/g, css: 'value' },
{ regex: new RegExp(this.getKeywords(funcs), 'gmi'), css: 'functions' },
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' },
{ regex: new RegExp(this.getKeywords(special), 'gm'), css: 'color1' }
];
this.forHtmlScript(SyntaxHighlighter.regexLib.aspScriptTags);
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['py', 'python'];
SyntaxHighlighter.brushes.Python = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
//}}}
//{{{
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function process(match, regexInfo)
{
var constructor = SyntaxHighlighter.Match,
code = match[0],
tag = new XRegExp('(<|<)[\\s\\/\\?]*(?<name>[:\\w-\\.]+)', 'xg').exec(code),
result = []
;
if (match.attributes != null)
{
var attributes,
regex = new XRegExp('(?<name> [\\w:\\-\\.]+)' +
'\\s*=\\s*' +
'(?<value> ".*?"|\'.*?\'|\\w+)',
'xg');
while ((attributes = regex.exec(code)) != null)
{
result.push(new constructor(attributes.name, match.index + attributes.index, 'color1'));
result.push(new constructor(attributes.value, match.index + attributes.index + attributes[0].indexOf(attributes.value), 'string'));
}
}
if (tag != null)
result.push(
new constructor(tag.name, match.index + tag[0].indexOf(tag.name), 'keyword')
);
return result;
}
this.regexList = [
{ regex: new XRegExp('(\\<|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\>|>)', 'gm'), css: 'color2' }, // <![ ... [ ... ]]>
{ regex: SyntaxHighlighter.regexLib.xmlComments, css: 'comments' }, // <!-- ... -->
{ regex: new XRegExp('(<|<)[\\s\\/\\?]*(\\w+)(?<attributes>.*?)[\\s\\/\\?]*(>|>)', 'sg'), func: process }
];
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['xml', 'xhtml', 'xslt', 'html'];
SyntaxHighlighter.brushes.Xml = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
//}}}
/*{{{*/
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter a,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody,
.syntaxhighlighter table thead,
.syntaxhighlighter table caption,
.syntaxhighlighter textarea {
-moz-border-radius: 0 0 0 0 !important;
-webkit-border-radius: 0 0 0 0 !important;
background: none !important;
border: 0 !important;
bottom: auto !important;
float: none !important;
height: auto !important;
left: auto !important;
line-height: 1.1em !important;
margin: 0 !important;
outline: 0 !important;
overflow: visible !important;
padding: 0 !important;
position: static !important;
right: auto !important;
text-align: left !important;
top: auto !important;
vertical-align: baseline !important;
width: auto !important;
box-sizing: content-box !important;
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
font-weight: normal !important;
font-style: normal !important;
font-size: 1em !important;
min-height: inherit !important;
min-height: auto !important;
}
.syntaxhighlighter {
width: 100% !important;
margin: 1em 0 1em 0 !important;
position: relative !important;
overflow: auto !important;
font-size: .9em !important;
}
.syntaxhighlighter.source {
overflow: hidden !important;
}
.syntaxhighlighter .bold {
font-weight: bold !important;
}
.syntaxhighlighter .italic {
font-style: italic !important;
}
.syntaxhighlighter .line {
white-space: pre !important;
}
.syntaxhighlighter table {
width: 100% !important;
}
.syntaxhighlighter table caption {
text-align: left !important;
padding: .5em 0 0.5em 1em !important;
}
.syntaxhighlighter table td.code {
width: 100% !important;
}
.syntaxhighlighter table td.code .container {
position: relative !important;
}
.syntaxhighlighter table td.code .container textarea {
box-sizing: border-box !important;
position: absolute !important;
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
border: none !important;
background: white !important;
padding-left: 1em !important;
overflow: hidden !important;
white-space: pre !important;
}
.syntaxhighlighter table td.gutter .line {
text-align: right !important;
padding: 0 0.5em 0 1em !important;
}
.syntaxhighlighter table td.code .line {
padding: 0 1em !important;
}
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
padding-left: 0em !important;
}
.syntaxhighlighter.show {
display: block !important;
}
.syntaxhighlighter.collapsed table {
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar {
padding: 0.1em 0.8em 0em 0.8em !important;
font-size: 1em !important;
position: static !important;
width: auto !important;
height: auto !important;
}
.syntaxhighlighter.collapsed .toolbar span {
display: inline !important;
margin-right: 1em !important;
}
.syntaxhighlighter.collapsed .toolbar span a {
padding: 0 !important;
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
display: inline !important;
}
.syntaxhighlighter .toolbar {
position: absolute !important;
right: 1px !important;
top: 1px !important;
width: 11px !important;
height: 11px !important;
font-size: 10px !important;
z-index: 10 !important;
}
.syntaxhighlighter .toolbar span.title {
display: inline !important;
}
.syntaxhighlighter .toolbar a {
display: block !important;
text-align: center !important;
text-decoration: none !important;
padding-top: 1px !important;
}
.syntaxhighlighter .toolbar a.expandSource {
display: none !important;
}
.syntaxhighlighter.ie {
font-size: .9em !important;
padding: 1px 0 1px 0 !important;
}
.syntaxhighlighter.ie .toolbar {
line-height: 8px !important;
}
.syntaxhighlighter.ie .toolbar a {
padding-top: 0px !important;
}
.syntaxhighlighter.printing .line.alt1 .content,
.syntaxhighlighter.printing .line.alt2 .content,
.syntaxhighlighter.printing .line.highlighted .number,
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
background: none !important;
}
.syntaxhighlighter.printing .line .number {
color: #bbbbbb !important;
}
.syntaxhighlighter.printing .line .content {
color: black !important;
}
.syntaxhighlighter.printing .toolbar {
display: none !important;
}
.syntaxhighlighter.printing a {
text-decoration: none !important;
}
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
color: black !important;
}
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
color: #008200 !important;
}
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
color: blue !important;
}
.syntaxhighlighter.printing .keyword {
color: #006699 !important;
font-weight: bold !important;
}
.syntaxhighlighter.printing .preprocessor {
color: gray !important;
}
.syntaxhighlighter.printing .variable {
color: #aa7700 !important;
}
.syntaxhighlighter.printing .value {
color: #009900 !important;
}
.syntaxhighlighter.printing .functions {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .constants {
color: #0066cc !important;
}
.syntaxhighlighter.printing .script {
font-weight: bold !important;
}
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
color: gray !important;
}
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
color: red !important;
}
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
color: black !important;
}
/*}}}*/
/***
|Name|ShCore.js|
***/
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
//{{{
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('K M;I(M)1S 2U("2a\'t 4k M 4K 2g 3l 4G 4H");(6(){6 r(f,e){I(!M.1R(f))1S 3m("3s 15 4R");K a=f.1w;f=M(f.1m,t(f)+(e||""));I(a)f.1w={1m:a.1m,19:a.19?a.19.1a(0):N};H f}6 t(f){H(f.1J?"g":"")+(f.4s?"i":"")+(f.4p?"m":"")+(f.4v?"x":"")+(f.3n?"y":"")}6 B(f,e,a,b){K c=u.L,d,h,g;v=R;5K{O(;c--;){g=u[c];I(a&g.3r&&(!g.2p||g.2p.W(b))){g.2q.12=e;I((h=g.2q.X(f))&&h.P===e){d={3k:g.2b.W(b,h,a),1C:h};1N}}}}5v(i){1S i}5q{v=11}H d}6 p(f,e,a){I(3b.Z.1i)H f.1i(e,a);O(a=a||0;a<f.L;a++)I(f[a]===e)H a;H-1}M=6(f,e){K a=[],b=M.1B,c=0,d,h;I(M.1R(f)){I(e!==1d)1S 3m("2a\'t 5r 5I 5F 5B 5C 15 5E 5p");H r(f)}I(v)1S 2U("2a\'t W 3l M 59 5m 5g 5x 5i");e=e||"";O(d={2N:11,19:[],2K:6(g){H e.1i(g)>-1},3d:6(g){e+=g}};c<f.L;)I(h=B(f,c,b,d)){a.U(h.3k);c+=h.1C[0].L||1}Y I(h=n.X.W(z[b],f.1a(c))){a.U(h[0]);c+=h[0].L}Y{h=f.3a(c);I(h==="[")b=M.2I;Y I(h==="]")b=M.1B;a.U(h);c++}a=15(a.1K(""),n.Q.W(e,w,""));a.1w={1m:f,19:d.2N?d.19:N};H a};M.3v="1.5.0";M.2I=1;M.1B=2;K C=/\\$(?:(\\d\\d?|[$&`\'])|{([$\\w]+)})/g,w=/[^5h]+|([\\s\\S])(?=[\\s\\S]*\\1)/g,A=/^(?:[?*+]|{\\d+(?:,\\d*)?})\\??/,v=11,u=[],n={X:15.Z.X,1A:15.Z.1A,1C:1r.Z.1C,Q:1r.Z.Q,1e:1r.Z.1e},x=n.X.W(/()??/,"")[1]===1d,D=6(){K f=/^/g;n.1A.W(f,"");H!f.12}(),y=6(){K f=/x/g;n.Q.W("x",f,"");H!f.12}(),E=15.Z.3n!==1d,z={};z[M.2I]=/^(?:\\\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\\29-26-f]{2}|u[\\29-26-f]{4}|c[A-3o-z]|[\\s\\S]))/;z[M.1B]=/^(?:\\\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\\d*|x[\\29-26-f]{2}|u[\\29-26-f]{4}|c[A-3o-z]|[\\s\\S])|\\(\\?[:=!]|[?*+]\\?|{\\d+(?:,\\d*)?}\\??)/;M.1h=6(f,e,a,b){u.U({2q:r(f,"g"+(E?"y":"")),2b:e,3r:a||M.1B,2p:b||N})};M.2n=6(f,e){K a=f+"/"+(e||"");H M.2n[a]||(M.2n[a]=M(f,e))};M.3c=6(f){H r(f,"g")};M.5l=6(f){H f.Q(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,"\\\\$&")};M.5e=6(f,e,a,b){e=r(e,"g"+(b&&E?"y":""));e.12=a=a||0;f=e.X(f);H b?f&&f.P===a?f:N:f};M.3q=6(){M.1h=6(){1S 2U("2a\'t 55 1h 54 3q")}};M.1R=6(f){H 53.Z.1q.W(f)==="[2m 15]"};M.3p=6(f,e,a,b){O(K c=r(e,"g"),d=-1,h;h=c.X(f);){a.W(b,h,++d,f,c);c.12===h.P&&c.12++}I(e.1J)e.12=0};M.57=6(f,e){H 6 a(b,c){K d=e[c].1I?e[c]:{1I:e[c]},h=r(d.1I,"g"),g=[],i;O(i=0;i<b.L;i++)M.3p(b[i],h,6(k){g.U(d.3j?k[d.3j]||"":k[0])});H c===e.L-1||!g.L?g:a(g,c+1)}([f],0)};15.Z.1p=6(f,e){H J.X(e[0])};15.Z.W=6(f,e){H J.X(e)};15.Z.X=6(f){K e=n.X.1p(J,14),a;I(e){I(!x&&e.L>1&&p(e,"")>-1){a=15(J.1m,n.Q.W(t(J),"g",""));n.Q.W(f.1a(e.P),a,6(){O(K c=1;c<14.L-2;c++)I(14[c]===1d)e[c]=1d})}I(J.1w&&J.1w.19)O(K b=1;b<e.L;b++)I(a=J.1w.19[b-1])e[a]=e[b];!D&&J.1J&&!e[0].L&&J.12>e.P&&J.12--}H e};I(!D)15.Z.1A=6(f){(f=n.X.W(J,f))&&J.1J&&!f[0].L&&J.12>f.P&&J.12--;H!!f};1r.Z.1C=6(f){M.1R(f)||(f=15(f));I(f.1J){K e=n.1C.1p(J,14);f.12=0;H e}H f.X(J)};1r.Z.Q=6(f,e){K a=M.1R(f),b,c;I(a&&1j e.58()==="3f"&&e.1i("${")===-1&&y)H n.Q.1p(J,14);I(a){I(f.1w)b=f.1w.19}Y f+="";I(1j e==="6")c=n.Q.W(J,f,6(){I(b){14[0]=1f 1r(14[0]);O(K d=0;d<b.L;d++)I(b[d])14[0][b[d]]=14[d+1]}I(a&&f.1J)f.12=14[14.L-2]+14[0].L;H e.1p(N,14)});Y{c=J+"";c=n.Q.W(c,f,6(){K d=14;H n.Q.W(e,C,6(h,g,i){I(g)5b(g){24"$":H"$";24"&":H d[0];24"`":H d[d.L-1].1a(0,d[d.L-2]);24"\'":H d[d.L-1].1a(d[d.L-2]+d[0].L);5a:i="";g=+g;I(!g)H h;O(;g>d.L-3;){i=1r.Z.1a.W(g,-1)+i;g=1Q.3i(g/10)}H(g?d[g]||"":"$")+i}Y{g=+i;I(g<=d.L-3)H d[g];g=b?p(b,i):-1;H g>-1?d[g+1]:h}})})}I(a&&f.1J)f.12=0;H c};1r.Z.1e=6(f,e){I(!M.1R(f))H n.1e.1p(J,14);K a=J+"",b=[],c=0,d,h;I(e===1d||+e<0)e=5D;Y{e=1Q.3i(+e);I(!e)H[]}O(f=M.3c(f);d=f.X(a);){I(f.12>c){b.U(a.1a(c,d.P));d.L>1&&d.P<a.L&&3b.Z.U.1p(b,d.1a(1));h=d[0].L;c=f.12;I(b.L>=e)1N}f.12===d.P&&f.12++}I(c===a.L){I(!n.1A.W(f,"")||h)b.U("")}Y b.U(a.1a(c));H b.L>e?b.1a(0,e):b};M.1h(/\\(\\?#[^)]*\\)/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"});M.1h(/\\((?!\\?)/,6(){J.19.U(N);H"("});M.1h(/\\(\\?<([$\\w]+)>/,6(f){J.19.U(f[1]);J.2N=R;H"("});M.1h(/\\\\k<([\\w$]+)>/,6(f){K e=p(J.19,f[1]);H e>-1?"\\\\"+(e+1)+(3R(f.2S.3a(f.P+f[0].L))?"":"(?:)"):f[0]});M.1h(/\\[\\^?]/,6(f){H f[0]==="[]"?"\\\\b\\\\B":"[\\\\s\\\\S]"});M.1h(/^\\(\\?([5A]+)\\)/,6(f){J.3d(f[1]);H""});M.1h(/(?:\\s+|#.*)+/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"},M.1B,6(){H J.2K("x")});M.1h(/\\./,6(){H"[\\\\s\\\\S]"},M.1B,6(){H J.2K("s")})})();1j 2e!="1d"&&(2e.M=M);K 1v=6(){6 r(a,b){a.1l.1i(b)!=-1||(a.1l+=" "+b)}6 t(a){H a.1i("3e")==0?a:"3e"+a}6 B(a){H e.1Y.2A[t(a)]}6 p(a,b,c){I(a==N)H N;K d=c!=R?a.3G:[a.2G],h={"#":"1c",".":"1l"}[b.1o(0,1)]||"3h",g,i;g=h!="3h"?b.1o(1):b.5u();I((a[h]||"").1i(g)!=-1)H a;O(a=0;d&&a<d.L&&i==N;a++)i=p(d[a],b,c);H i}6 C(a,b){K c={},d;O(d 2g a)c[d]=a[d];O(d 2g b)c[d]=b[d];H c}6 w(a,b,c,d){6 h(g){g=g||1P.5y;I(!g.1F){g.1F=g.52;g.3N=6(){J.5w=11}}c.W(d||1P,g)}a.3g?a.3g("4U"+b,h):a.4y(b,h,11)}6 A(a,b){K c=e.1Y.2j,d=N;I(c==N){c={};O(K h 2g e.1U){K g=e.1U[h];d=g.4x;I(d!=N){g.1V=h.4w();O(g=0;g<d.L;g++)c[d[g]]=h}}e.1Y.2j=c}d=e.1U[c[a]];d==N&&b!=11&&1P.1X(e.13.1x.1X+(e.13.1x.3E+a));H d}6 v(a,b){O(K c=a.1e("\\n"),d=0;d<c.L;d++)c[d]=b(c[d],d);H c.1K("\\n")}6 u(a,b){I(a==N||a.L==0||a=="\\n")H a;a=a.Q(/</g,"&1y;");a=a.Q(/ {2,}/g,6(c){O(K d="",h=0;h<c.L-1;h++)d+=e.13.1W;H d+" "});I(b!=N)a=v(a,6(c){I(c.L==0)H"";K d="";c=c.Q(/^(&2s;| )+/,6(h){d=h;H""});I(c.L==0)H d;H d+\'<17 1g="\'+b+\'">\'+c+"</17>"});H a}6 n(a,b){a.1e("\\n");O(K c="",d=0;d<50;d++)c+=" ";H a=v(a,6(h){I(h.1i("\\t")==-1)H h;O(K g=0;(g=h.1i("\\t"))!=-1;)h=h.1o(0,g)+c.1o(0,b-g%b)+h.1o(g+1,h.L);H h})}6 x(a){H a.Q(/^\\s+|\\s+$/g,"")}6 D(a,b){I(a.P<b.P)H-1;Y I(a.P>b.P)H 1;Y I(a.L<b.L)H-1;Y I(a.L>b.L)H 1;H 0}6 y(a,b){6 c(k){H k[0]}O(K d=N,h=[],g=b.2D?b.2D:c;(d=b.1I.X(a))!=N;){K i=g(d,b);I(1j i=="3f")i=[1f e.2L(i,d.P,b.23)];h=h.1O(i)}H h}6 E(a){K b=/(.*)((&1G;|&1y;).*)/;H a.Q(e.3A.3M,6(c){K d="",h=N;I(h=b.X(c)){c=h[1];d=h[2]}H\'<a 2h="\'+c+\'">\'+c+"</a>"+d})}6 z(){O(K a=1E.36("1k"),b=[],c=0;c<a.L;c++)a[c].3s=="20"&&b.U(a[c]);H b}6 f(a){a=a.1F;K b=p(a,".20",R);a=p(a,".3O",R);K c=1E.4i("3t");I(!(!a||!b||p(a,"3t"))){B(b.1c);r(b,"1m");O(K d=a.3G,h=[],g=0;g<d.L;g++)h.U(d[g].4z||d[g].4A);h=h.1K("\\r");c.39(1E.4D(h));a.39(c);c.2C();c.4C();w(c,"4u",6(){c.2G.4E(c);b.1l=b.1l.Q("1m","")})}}I(1j 3F!="1d"&&1j M=="1d")M=3F("M").M;K e={2v:{"1g-27":"","2i-1s":1,"2z-1s-2t":11,1M:N,1t:N,"42-45":R,"43-22":4,1u:R,16:R,"3V-17":R,2l:11,"41-40":R,2k:11,"1z-1k":11},13:{1W:"&2s;",2M:R,46:11,44:11,34:"4n",1x:{21:"4o 1m",2P:"?",1X:"1v\\n\\n",3E:"4r\'t 4t 1D O: ",4g:"4m 4B\'t 51 O 1z-1k 4F: ",37:\'<!4T 1z 4S "-//4V//3H 4W 1.0 4Z//4Y" "1Z://2y.3L.3K/4X/3I/3H/3I-4P.4J"><1z 4I="1Z://2y.3L.3K/4L/5L"><3J><4N 1Z-4M="5G-5M" 6K="2O/1z; 6J=6I-8" /><1t>6L 1v</1t></3J><3B 1L="25-6M:6Q,6P,6O,6N-6F;6y-2f:#6x;2f:#6w;25-22:6v;2O-3D:3C;"><T 1L="2O-3D:3C;3w-32:1.6z;"><T 1L="25-22:6A-6E;">1v</T><T 1L="25-22:.6C;3w-6B:6R;"><T>3v 3.0.76 (72 73 3x)</T><T><a 2h="1Z://3u.2w/1v" 1F="38" 1L="2f:#3y">1Z://3u.2w/1v</a></T><T>70 17 6U 71.</T><T>6T 6X-3x 6Y 6D.</T></T><T>6t 61 60 J 1k, 5Z <a 2h="6u://2y.62.2w/63-66/65?64=5X-5W&5P=5O" 1L="2f:#3y">5R</a> 5V <2R/>5U 5T 5S!</T></T></3B></1z>\'}},1Y:{2j:N,2A:{}},1U:{},3A:{6n:/\\/\\*[\\s\\S]*?\\*\\//2c,6m:/\\/\\/.*$/2c,6l:/#.*$/2c,6k:/"([^\\\\"\\n]|\\\\.)*"/g,6o:/\'([^\\\\\'\\n]|\\\\.)*\'/g,6p:1f M(\'"([^\\\\\\\\"]|\\\\\\\\.)*"\',"3z"),6s:1f M("\'([^\\\\\\\\\']|\\\\\\\\.)*\'","3z"),6q:/(&1y;|<)!--[\\s\\S]*?--(&1G;|>)/2c,3M:/\\w+:\\/\\/[\\w-.\\/?%&=:@;]*/g,6a:{18:/(&1y;|<)\\?=?/g,1b:/\\?(&1G;|>)/g},69:{18:/(&1y;|<)%=?/g,1b:/%(&1G;|>)/g},6d:{18:/(&1y;|<)\\s*1k.*?(&1G;|>)/2T,1b:/(&1y;|<)\\/\\s*1k\\s*(&1G;|>)/2T}},16:{1H:6(a){6 b(i,k){H e.16.2o(i,k,e.13.1x[k])}O(K c=\'<T 1g="16">\',d=e.16.2x,h=d.2X,g=0;g<h.L;g++)c+=(d[h[g]].1H||b)(a,h[g]);c+="</T>";H c},2o:6(a,b,c){H\'<2W><a 2h="#" 1g="6e 6h\'+b+" "+b+\'">\'+c+"</a></2W>"},2b:6(a){K b=a.1F,c=b.1l||"";b=B(p(b,".20",R).1c);K d=6(h){H(h=15(h+"6f(\\\\w+)").X(c))?h[1]:N}("6g");b&&d&&e.16.2x[d].2B(b);a.3N()},2x:{2X:["21","2P"],21:{1H:6(a){I(a.V("2l")!=R)H"";K b=a.V("1t");H e.16.2o(a,"21",b?b:e.13.1x.21)},2B:6(a){a=1E.6j(t(a.1c));a.1l=a.1l.Q("47","")}},2P:{2B:6(){K a="68=0";a+=", 18="+(31.30-33)/2+", 32="+(31.2Z-2Y)/2+", 30=33, 2Z=2Y";a=a.Q(/^,/,"");a=1P.6Z("","38",a);a.2C();K b=a.1E;b.6W(e.13.1x.37);b.6V();a.2C()}}}},35:6(a,b){K c;I(b)c=[b];Y{c=1E.36(e.13.34);O(K d=[],h=0;h<c.L;h++)d.U(c[h]);c=d}c=c;d=[];I(e.13.2M)c=c.1O(z());I(c.L===0)H d;O(h=0;h<c.L;h++){O(K g=c[h],i=a,k=c[h].1l,j=3W 0,l={},m=1f M("^\\\\[(?<2V>(.*?))\\\\]$"),s=1f M("(?<27>[\\\\w-]+)\\\\s*:\\\\s*(?<1T>[\\\\w-%#]+|\\\\[.*?\\\\]|\\".*?\\"|\'.*?\')\\\\s*;?","g");(j=s.X(k))!=N;){K o=j.1T.Q(/^[\'"]|[\'"]$/g,"");I(o!=N&&m.1A(o)){o=m.X(o);o=o.2V.L>0?o.2V.1e(/\\s*,\\s*/):[]}l[j.27]=o}g={1F:g,1n:C(i,l)};g.1n.1D!=N&&d.U(g)}H d},1M:6(a,b){K c=J.35(a,b),d=N,h=e.13;I(c.L!==0)O(K g=0;g<c.L;g++){b=c[g];K i=b.1F,k=b.1n,j=k.1D,l;I(j!=N){I(k["1z-1k"]=="R"||e.2v["1z-1k"]==R){d=1f e.4l(j);j="4O"}Y I(d=A(j))d=1f d;Y 6H;l=i.3X;I(h.2M){l=l;K m=x(l),s=11;I(m.1i("<![6G[")==0){m=m.4h(9);s=R}K o=m.L;I(m.1i("]]\\>")==o-3){m=m.4h(0,o-3);s=R}l=s?m:l}I((i.1t||"")!="")k.1t=i.1t;k.1D=j;d.2Q(k);b=d.2F(l);I((i.1c||"")!="")b.1c=i.1c;i.2G.74(b,i)}}},2E:6(a){w(1P,"4k",6(){e.1M(a)})}};e.2E=e.2E;e.1M=e.1M;e.2L=6(a,b,c){J.1T=a;J.P=b;J.L=a.L;J.23=c;J.1V=N};e.2L.Z.1q=6(){H J.1T};e.4l=6(a){6 b(j,l){O(K m=0;m<j.L;m++)j[m].P+=l}K c=A(a),d,h=1f e.1U.5Y,g=J,i="2F 1H 2Q".1e(" ");I(c!=N){d=1f c;O(K k=0;k<i.L;k++)(6(){K j=i[k];g[j]=6(){H h[j].1p(h,14)}})();d.28==N?1P.1X(e.13.1x.1X+(e.13.1x.4g+a)):h.2J.U({1I:d.28.17,2D:6(j){O(K l=j.17,m=[],s=d.2J,o=j.P+j.18.L,F=d.28,q,G=0;G<s.L;G++){q=y(l,s[G]);b(q,o);m=m.1O(q)}I(F.18!=N&&j.18!=N){q=y(j.18,F.18);b(q,j.P);m=m.1O(q)}I(F.1b!=N&&j.1b!=N){q=y(j.1b,F.1b);b(q,j.P+j[0].5Q(j.1b));m=m.1O(q)}O(j=0;j<m.L;j++)m[j].1V=c.1V;H m}})}};e.4j=6(){};e.4j.Z={V:6(a,b){K c=J.1n[a];c=c==N?b:c;K d={"R":R,"11":11}[c];H d==N?c:d},3Y:6(a){H 1E.4i(a)},4c:6(a,b){K c=[];I(a!=N)O(K d=0;d<a.L;d++)I(1j a[d]=="2m")c=c.1O(y(b,a[d]));H J.4e(c.6b(D))},4e:6(a){O(K b=0;b<a.L;b++)I(a[b]!==N)O(K c=a[b],d=c.P+c.L,h=b+1;h<a.L&&a[b]!==N;h++){K g=a[h];I(g!==N)I(g.P>d)1N;Y I(g.P==c.P&&g.L>c.L)a[b]=N;Y I(g.P>=c.P&&g.P<d)a[h]=N}H a},4d:6(a){K b=[],c=2u(J.V("2i-1s"));v(a,6(d,h){b.U(h+c)});H b},3U:6(a){K b=J.V("1M",[]);I(1j b!="2m"&&b.U==N)b=[b];a:{a=a.1q();K c=3W 0;O(c=c=1Q.6c(c||0,0);c<b.L;c++)I(b[c]==a){b=c;1N a}b=-1}H b!=-1},2r:6(a,b,c){a=["1s","6i"+b,"P"+a,"6r"+(b%2==0?1:2).1q()];J.3U(b)&&a.U("67");b==0&&a.U("1N");H\'<T 1g="\'+a.1K(" ")+\'">\'+c+"</T>"},3Q:6(a,b){K c="",d=a.1e("\\n").L,h=2u(J.V("2i-1s")),g=J.V("2z-1s-2t");I(g==R)g=(h+d-1).1q().L;Y I(3R(g)==R)g=0;O(K i=0;i<d;i++){K k=b?b[i]:h+i,j;I(k==0)j=e.13.1W;Y{j=g;O(K l=k.1q();l.L<j;)l="0"+l;j=l}a=j;c+=J.2r(i,k,a)}H c},49:6(a,b){a=x(a);K c=a.1e("\\n");J.V("2z-1s-2t");K d=2u(J.V("2i-1s"));a="";O(K h=J.V("1D"),g=0;g<c.L;g++){K i=c[g],k=/^(&2s;|\\s)+/.X(i),j=N,l=b?b[g]:d+g;I(k!=N){j=k[0].1q();i=i.1o(j.L);j=j.Q(" ",e.13.1W)}i=x(i);I(i.L==0)i=e.13.1W;a+=J.2r(g,l,(j!=N?\'<17 1g="\'+h+\' 5N">\'+j+"</17>":"")+i)}H a},4f:6(a){H a?"<4a>"+a+"</4a>":""},4b:6(a,b){6 c(l){H(l=l?l.1V||g:g)?l+" ":""}O(K d=0,h="",g=J.V("1D",""),i=0;i<b.L;i++){K k=b[i],j;I(!(k===N||k.L===0)){j=c(k);h+=u(a.1o(d,k.P-d),j+"48")+u(k.1T,j+k.23);d=k.P+k.L+(k.75||0)}}h+=u(a.1o(d),c()+"48");H h},1H:6(a){K b="",c=["20"],d;I(J.V("2k")==R)J.1n.16=J.1n.1u=11;1l="20";J.V("2l")==R&&c.U("47");I((1u=J.V("1u"))==11)c.U("6S");c.U(J.V("1g-27"));c.U(J.V("1D"));a=a.Q(/^[ ]*[\\n]+|[\\n]*[ ]*$/g,"").Q(/\\r/g," ");b=J.V("43-22");I(J.V("42-45")==R)a=n(a,b);Y{O(K h="",g=0;g<b;g++)h+=" ";a=a.Q(/\\t/g,h)}a=a;a:{b=a=a;h=/<2R\\s*\\/?>|&1y;2R\\s*\\/?&1G;/2T;I(e.13.46==R)b=b.Q(h,"\\n");I(e.13.44==R)b=b.Q(h,"");b=b.1e("\\n");h=/^\\s*/;g=4Q;O(K i=0;i<b.L&&g>0;i++){K k=b[i];I(x(k).L!=0){k=h.X(k);I(k==N){a=a;1N a}g=1Q.4q(k[0].L,g)}}I(g>0)O(i=0;i<b.L;i++)b[i]=b[i].1o(g);a=b.1K("\\n")}I(1u)d=J.4d(a);b=J.4c(J.2J,a);b=J.4b(a,b);b=J.49(b,d);I(J.V("41-40"))b=E(b);1j 2H!="1d"&&2H.3S&&2H.3S.1C(/5s/)&&c.U("5t");H b=\'<T 1c="\'+t(J.1c)+\'" 1g="\'+c.1K(" ")+\'">\'+(J.V("16")?e.16.1H(J):"")+\'<3Z 5z="0" 5H="0" 5J="0">\'+J.4f(J.V("1t"))+"<3T><3P>"+(1u?\'<2d 1g="1u">\'+J.3Q(a)+"</2d>":"")+\'<2d 1g="17"><T 1g="3O">\'+b+"</T></2d></3P></3T></3Z></T>"},2F:6(a){I(a===N)a="";J.17=a;K b=J.3Y("T");b.3X=J.1H(a);J.V("16")&&w(p(b,".16"),"5c",e.16.2b);J.V("3V-17")&&w(p(b,".17"),"56",f);H b},2Q:6(a){J.1c=""+1Q.5d(1Q.5n()*5k).1q();e.1Y.2A[t(J.1c)]=J;J.1n=C(e.2v,a||{});I(J.V("2k")==R)J.1n.16=J.1n.1u=11},5j:6(a){a=a.Q(/^\\s+|\\s+$/g,"").Q(/\\s+/g,"|");H"\\\\b(?:"+a+")\\\\b"},5f:6(a){J.28={18:{1I:a.18,23:"1k"},1b:{1I:a.1b,23:"1k"},17:1f M("(?<18>"+a.18.1m+")(?<17>.*?)(?<1b>"+a.1b.1m+")","5o")}}};H e}();1j 2e!="1d"&&(2e.1v=1v);',62,441,'||||||function|||||||||||||||||||||||||||||||||||||return|if|this|var|length|XRegExp|null|for|index|replace|true||div|push|getParam|call|exec|else|prototype||false|lastIndex|config|arguments|RegExp|toolbar|code|left|captureNames|slice|right|id|undefined|split|new|class|addToken|indexOf|typeof|script|className|source|params|substr|apply|toString|String|line|title|gutter|SyntaxHighlighter|_xregexp|strings|lt|html|test|OUTSIDE_CLASS|match|brush|document|target|gt|getHtml|regex|global|join|style|highlight|break|concat|window|Math|isRegExp|throw|value|brushes|brushName|space|alert|vars|http|syntaxhighlighter|expandSource|size|css|case|font|Fa|name|htmlScript|dA|can|handler|gm|td|exports|color|in|href|first|discoveredBrushes|light|collapse|object|cache|getButtonHtml|trigger|pattern|getLineHtml|nbsp|numbers|parseInt|defaults|com|items|www|pad|highlighters|execute|focus|func|all|getDiv|parentNode|navigator|INSIDE_CLASS|regexList|hasFlag|Match|useScriptTags|hasNamedCapture|text|help|init|br|input|gi|Error|values|span|list|250|height|width|screen|top|500|tagName|findElements|getElementsByTagName|aboutDialog|_blank|appendChild|charAt|Array|copyAsGlobal|setFlag|highlighter_|string|attachEvent|nodeName|floor|backref|output|the|TypeError|sticky|Za|iterate|freezeTokens|scope|type|textarea|alexgorbatchev|version|margin|2010|005896|gs|regexLib|body|center|align|noBrush|require|childNodes|DTD|xhtml1|head|org|w3|url|preventDefault|container|tr|getLineNumbersHtml|isNaN|userAgent|tbody|isLineHighlighted|quick|void|innerHTML|create|table|links|auto|smart|tab|stripBrs|tabs|bloggerMode|collapsed|plain|getCodeLinesHtml|caption|getMatchesHtml|findMatches|figureOutLineNumbers|removeNestedMatches|getTitleHtml|brushNotHtmlScript|substring|createElement|Highlighter|load|HtmlScript|Brush|pre|expand|multiline|min|Can|ignoreCase|find|blur|extended|toLowerCase|aliases|addEventListener|innerText|textContent|wasn|select|createTextNode|removeChild|option|same|frame|xmlns|dtd|twice|1999|equiv|meta|htmlscript|transitional|1E3|expected|PUBLIC|DOCTYPE|on|W3C|XHTML|TR|EN|Transitional||configured|srcElement|Object|after|run|dblclick|matchChain|valueOf|constructor|default|switch|click|round|execAt|forHtmlScript|token|gimy|functions|getKeywords|1E6|escape|within|random|sgi|another|finally|supply|MSIE|ie|toUpperCase|catch|returnValue|definition|event|border|imsx|constructing|one|Infinity|from|when|Content|cellpadding|flags|cellspacing|try|xhtml|Type|spaces|2930402|hosted_button_id|lastIndexOf|donate|active|development|keep|to|xclick|_s|Xml|please|like|you|paypal|cgi|cmd|webscr|bin|highlighted|scrollbars|aspScriptTags|phpScriptTags|sort|max|scriptScriptTags|toolbar_item|_|command|command_|number|getElementById|doubleQuotedString|singleLinePerlComments|singleLineCComments|multiLineCComments|singleQuotedString|multiLineDoubleQuotedString|xmlComments|alt|multiLineSingleQuotedString|If|https|1em|000|fff|background|5em|xx|bottom|75em|Gorbatchev|large|serif|CDATA|continue|utf|charset|content|About|family|sans|Helvetica|Arial|Geneva|3em|nogutter|Copyright|syntax|close|write|2004|Alex|open|JavaScript|highlighter|July|02|replaceChild|offset|83'.split('|'),0,{}))
//}}}
/*{{{*/
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter {
background-color: white !important;
}
.syntaxhighlighter .line.alt1 {
background-color: white !important;
}
.syntaxhighlighter .line.alt2 {
background-color: white !important;
}
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
background-color: #e0e0e0 !important;
}
.syntaxhighlighter .line.highlighted.number {
color: black !important;
}
.syntaxhighlighter table caption {
color: black !important;
}
.syntaxhighlighter .gutter {
color: #afafaf !important;
}
.syntaxhighlighter .gutter .line {
border-right: 3px solid #6ce26c !important;
}
.syntaxhighlighter .gutter .line.highlighted {
background-color: #6ce26c !important;
color: white !important;
}
.syntaxhighlighter.printing .line .content {
border: none !important;
}
.syntaxhighlighter.collapsed {
overflow: visible !important;
}
.syntaxhighlighter.collapsed .toolbar {
color: blue !important;
background: white !important;
border: 1px solid #6ce26c !important;
}
.syntaxhighlighter.collapsed .toolbar a {
color: blue !important;
}
.syntaxhighlighter.collapsed .toolbar a:hover {
color: red !important;
}
.syntaxhighlighter .toolbar {
color: white !important;
background: #6ce26c !important;
border: none !important;
}
.syntaxhighlighter .toolbar a {
color: white !important;
}
.syntaxhighlighter .toolbar a:hover {
color: black !important;
}
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
color: black !important;
}
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
color: #008200 !important;
}
.syntaxhighlighter .string, .syntaxhighlighter .string a {
color: blue !important;
}
.syntaxhighlighter .keyword {
color: #006699 !important;
}
.syntaxhighlighter .preprocessor {
color: gray !important;
}
.syntaxhighlighter .variable {
color: #aa7700 !important;
}
.syntaxhighlighter .value {
color: #009900 !important;
}
.syntaxhighlighter .functions {
color: #ff1493 !important;
}
.syntaxhighlighter .constants {
color: #0066cc !important;
}
.syntaxhighlighter .script {
font-weight: bold !important;
color: #006699 !important;
background-color: none !important;
}
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
color: gray !important;
}
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
color: red !important;
}
.syntaxhighlighter .keyword {
font-weight: bold !important;
}
/*}}}*/
/***
<<highlightSyntax>>
***/
start:May 28 2006 09:00:00 GMT
end:Jun 15 2006 09:00:00 GMT
isDuration:true
title:Writing Timeline documentation
image:http://simile.mit.edu/images/csail-logo.gif
description:A few days to write some documentation for <a href:http://simile.mit.edu/timeline/>Timeline</a>.
start:Jun 16 2006 00:00:00 GMT
end:Jun 26 2006 00:00:00 GMT
title:Friend's wedding
description:I'm not sure precisely when my friend's wedding is.
start:Aug 02 2006 00:00:00 GMT
title:Trip to Beijing
link:http://travel.yahoo.com/
description:Woohoo!
start:Aug 02 2006 08:35:00 GMT-0500
title:Board plane in Boston
start:Aug 02 2006 10:35:00 GMT-0500
title:Land in Newwark, New York
start:Aug 02 2006 11:55:00 GMT-0500
title:Board plane in Newwark, New York
start:Aug 03 2006 03:30:00 GMT-0500
title:Land in Beijing in China
start:Aug 03 2006 07:00:00 GMT-0500
title:Dinner with old colleagues
/***
|''Name:''|SimileTimelineBundlePlugin|
|''Description:''|[[Simile Timelines|http://simile.mit.edu/SimileTimeline/]] |
|''Author:''|Martin Budden (mjbudden [at] gmail [dot] com)|
|''Source:''|http://www.martinswiki.com/#SimileTimelineBundlePlugin |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/plugins/SimileTimelineBundlePlugin.js |
|''Version:''|0.1.0|
|''Date:''|Mar 4, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|BSD-style license from MIT|
|''~CoreVersion:''|2.2|
***/
/*{{{*/
// Ensure that the SimileTimelineBundlePlugin is only installed once.
if(!version.extensions.SimileTimelineBundlePlugin) {
version.extensions.SimileTimelineBundlePlugin = {installed:true};
if(version.major < 2 || (version.major == 2 && version.minor < 2))
{alertAndThrow('SimileTimelineBundlePlugin requires TiddlyWiki 2.2 or newer.');}
// Following code is from Simile (Semantic Interoperability of Metadata and Information in unLike Environments).
// SIMILE is a joint project conducted by the MIT Libraries and MIT CSAIL.
// Code is released under a BSD-style license.
// See:
// http://simile.mit.edu/repository/timeline/trunk/src/webapp/api/bundle.js
var Timeline = new Object();
Timeline.Platform = new Object();
Timeline.Platform.serverLocale = "en";
Timeline.Platform.clientLocale = "en";
/* timeline.js */
Timeline.strings={};Timeline.create=function(elmt,bandInfos,orientation,unit){return new Timeline._Impl(elmt,bandInfos,orientation,unit);};Timeline.HORIZONTAL=0;Timeline.VERTICAL=1;Timeline._defaultTheme=null;Timeline.createBandInfo=function(params){var theme=("theme"in params)?params.theme:Timeline.getDefaultTheme();var eventSource=("eventSource"in params)?params.eventSource:null;var ether=new Timeline.LinearEther({centersOn:("date"in params)?params.date:new Date(),interval:Timeline.DateTime.gregorianUnitLengths[params.intervalUnit],pixelsPerInterval:params.intervalPixels});var etherPainter=new Timeline.GregorianEtherPainter({unit:params.intervalUnit,multiple:("multiple"in params)?params.multiple:1,theme:theme,align:("align"in params)?params.align:undefined});var layout=new Timeline.StaticTrackBasedLayout({eventSource:eventSource,ether:ether,showText:("showEventText"in params)?params.showEventText:true,theme:theme});var eventPainterParams={showText:("showEventText"in params)?params.showEventText:true,layout:layout,theme:theme};if("trackHeight"in params){eventPainterParams.trackHeight=params.trackHeight;}
if("trackGap"in params){eventPainterParams.trackGap=params.trackGap;}
var eventPainter=new Timeline.DurationEventPainter(eventPainterParams);return{width:params.width,eventSource:eventSource,timeZone:("timeZone"in params)?params.timeZone:0,ether:ether,etherPainter:etherPainter,eventPainter:eventPainter};};Timeline.createHotZoneBandInfo=function(params){var theme=("theme"in params)?params.theme:Timeline.getDefaultTheme();var eventSource=("eventSource"in params)?params.eventSource:null;var ether=new Timeline.HotZoneEther({centersOn:("date"in params)?params.date:new Date(),interval:Timeline.DateTime.gregorianUnitLengths[params.intervalUnit],pixelsPerInterval:params.intervalPixels,zones:params.zones});var etherPainter=new Timeline.HotZoneGregorianEtherPainter({unit:params.intervalUnit,zones:params.zones,theme:theme,align:("align"in params)?params.align:undefined});var layout=new Timeline.StaticTrackBasedLayout({eventSource:eventSource,ether:ether,theme:theme});var eventPainterParams={showText:("showEventText"in params)?params.showEventText:true,layout:layout,theme:theme};if("trackHeight"in params){eventPainterParams.trackHeight=params.trackHeight;}
if("trackGap"in params){eventPainterParams.trackGap=params.trackGap;}
var eventPainter=new Timeline.DurationEventPainter(eventPainterParams);return{width:params.width,eventSource:eventSource,timeZone:("timeZone"in params)?params.timeZone:0,ether:ether,etherPainter:etherPainter,eventPainter:eventPainter};};Timeline.getDefaultTheme=function(){if(Timeline._defaultTheme==null){Timeline._defaultTheme=Timeline.ClassicTheme.create(Timeline.Platform.getDefaultLocale());}
return Timeline._defaultTheme;};Timeline.setDefaultTheme=function(theme){Timeline._defaultTheme=theme;};Timeline.loadXML=function(url,f){var fError=function(statusText,status,xmlhttp){alert("Failed to load data xml from "+url+"\n"+statusText);};var fDone=function(xmlhttp){var xml=xmlhttp.responseXML;if(!xml.documentElement&&xmlhttp.responseStream){xml.load(xmlhttp.responseStream);}
f(xml,url);};Timeline.XmlHttp.get(url,fError,fDone);};Timeline.loadJSON=function(url,f){var fError=function(statusText,status,xmlhttp){alert("Failed to load json data from "+url+"\n"+statusText);};var fDone=function(xmlhttp){f(eval('('+xmlhttp.responseText+')'),url);};Timeline.XmlHttp.get(url,fError,fDone);};Timeline._Impl=function(elmt,bandInfos,orientation,unit){this._containerDiv=elmt;this._bandInfos=bandInfos;this._orientation=orientation==null?Timeline.HORIZONTAL:orientation;this._unit=(unit!=null)?unit:Timeline.NativeDateUnit;this._initialize();};Timeline._Impl.prototype.dispose=function(){for(var i=0;i<this._bands.length;i++){this._bands[i].dispose();}
this._bands=null;this._bandInfos=null;this._containerDiv.innerHTML="";};Timeline._Impl.prototype.getBandCount=function(){return this._bands.length;};Timeline._Impl.prototype.getBand=function(index){return this._bands[index];};Timeline._Impl.prototype.layout=function(){this._distributeWidths();};Timeline._Impl.prototype.paint=function(){for(var i=0;i<this._bands.length;i++){this._bands[i].paint();}};Timeline._Impl.prototype.getDocument=function(){return this._containerDiv.ownerDocument;};Timeline._Impl.prototype.addDiv=function(div){this._containerDiv.appendChild(div);};Timeline._Impl.prototype.removeDiv=function(div){this._containerDiv.removeChild(div);};Timeline._Impl.prototype.isHorizontal=function(){return this._orientation==Timeline.HORIZONTAL;};Timeline._Impl.prototype.isVertical=function(){return this._orientation==Timeline.VERTICAL;};Timeline._Impl.prototype.getPixelLength=function(){return this._orientation==Timeline.HORIZONTAL?this._containerDiv.offsetWidth:this._containerDiv.offsetHeight;};Timeline._Impl.prototype.getPixelWidth=function(){return this._orientation==Timeline.VERTICAL?this._containerDiv.offsetWidth:this._containerDiv.offsetHeight;};Timeline._Impl.prototype.getUnit=function(){return this._unit;};Timeline._Impl.prototype.loadXML=function(url,f){var tl=this;var fError=function(statusText,status,xmlhttp){alert("Failed to load data xml from "+url+"\n"+statusText);tl.hideLoadingMessage();};var fDone=function(xmlhttp){try{var xml=xmlhttp.responseXML;if(!xml.documentElement&&xmlhttp.responseStream){xml.load(xmlhttp.responseStream);}
f(xml,url);}finally{tl.hideLoadingMessage();}};this.showLoadingMessage();window.setTimeout(function(){Timeline.XmlHttp.get(url,fError,fDone);},0);};Timeline._Impl.prototype.loadJSON=function(url,f){var tl=this;var fError=function(statusText,status,xmlhttp){alert("Failed to load json data from "+url+"\n"+statusText);tl.hideLoadingMessage();};var fDone=function(xmlhttp){try{f(eval('('+xmlhttp.responseText+')'),url);}finally{tl.hideLoadingMessage();}};this.showLoadingMessage();window.setTimeout(function(){Timeline.XmlHttp.get(url,fError,fDone);},0);};Timeline._Impl.prototype._initialize=function(){var containerDiv=this._containerDiv;var doc=containerDiv.ownerDocument;containerDiv.className=containerDiv.className.split(" ").concat("timeline-container").join(" ");while(containerDiv.firstChild){containerDiv.removeChild(containerDiv.firstChild);}
var elmtCopyright=Timeline.Graphics.createTranslucentImage(doc,Timeline.urlPrefix+(this.isHorizontal()?"images/copyright-vertical.png":"images/copyright.png"));elmtCopyright.className="timeline-copyright";elmtCopyright.title="Timeline (c) SIMILE - http://simile.mit.edu/timeline/";Timeline.DOM.registerEvent(elmtCopyright,"click",function(){window.location="http://simile.mit.edu/timeline/";});containerDiv.appendChild(elmtCopyright);this._bands=[];for(var i=0;i<this._bandInfos.length;i++){var band=new Timeline._Band(this,this._bandInfos[i],i);this._bands.push(band);}
this._distributeWidths();for(var i=0;i<this._bandInfos.length;i++){var bandInfo=this._bandInfos[i];if("syncWith"in bandInfo){this._bands[i].setSyncWithBand(this._bands[bandInfo.syncWith],("highlight"in bandInfo)?bandInfo.highlight:false);}}
var message=Timeline.Graphics.createMessageBubble(doc);message.containerDiv.className="timeline-message-container";containerDiv.appendChild(message.containerDiv);message.contentDiv.className="timeline-message";message.contentDiv.innerHTML="<img src='"+Timeline.urlPrefix+"images/progress-running.gif' /> Loading...";this.showLoadingMessage=function(){message.containerDiv.style.display="block";};this.hideLoadingMessage=function(){message.containerDiv.style.display="none";};};Timeline._Impl.prototype._distributeWidths=function(){var length=this.getPixelLength();var width=this.getPixelWidth();var cumulativeWidth=0;for(var i=0;i<this._bands.length;i++){var band=this._bands[i];var bandInfos=this._bandInfos[i];var widthString=bandInfos.width;var x=widthString.indexOf("%");if(x>0){var percent=parseInt(widthString.substr(0,x));var bandWidth=percent*width/100;}else{var bandWidth=parseInt(widthString);}
band.setBandShiftAndWidth(cumulativeWidth,bandWidth);band.setViewLength(length);cumulativeWidth+=bandWidth;}};Timeline._Band=function(timeline,bandInfo,index){this._timeline=timeline;this._bandInfo=bandInfo;this._index=index;this._locale=("locale"in bandInfo)?bandInfo.locale:Timeline.Platform.getDefaultLocale();this._timeZone=("timeZone"in bandInfo)?bandInfo.timeZone:0;this._labeller=("labeller"in bandInfo)?bandInfo.labeller:timeline.getUnit().createLabeller(this._locale,this._timeZone);this._dragging=false;this._changing=false;this._originalScrollSpeed=5;this._scrollSpeed=this._originalScrollSpeed;this._onScrollListeners=[];var b=this;this._syncWithBand=null;this._syncWithBandHandler=function(band){b._onHighlightBandScroll();};this._selectorListener=function(band){b._onHighlightBandScroll();};var inputDiv=this._timeline.getDocument().createElement("div");inputDiv.className="timeline-band-input";this._timeline.addDiv(inputDiv);this._keyboardInput=document.createElement("input");this._keyboardInput.type="text";inputDiv.appendChild(this._keyboardInput);Timeline.DOM.registerEventWithObject(this._keyboardInput,"keydown",this,this._onKeyDown);Timeline.DOM.registerEventWithObject(this._keyboardInput,"keyup",this,this._onKeyUp);this._div=this._timeline.getDocument().createElement("div");this._div.className="timeline-band";this._timeline.addDiv(this._div);Timeline.DOM.registerEventWithObject(this._div,"mousedown",this,this._onMouseDown);Timeline.DOM.registerEventWithObject(this._div,"mousemove",this,this._onMouseMove);Timeline.DOM.registerEventWithObject(this._div,"mouseup",this,this._onMouseUp);Timeline.DOM.registerEventWithObject(this._div,"mouseout",this,this._onMouseOut);Timeline.DOM.registerEventWithObject(this._div,"dblclick",this,this._onDblClick);this._innerDiv=this._timeline.getDocument().createElement("div");this._innerDiv.className="timeline-band-inner";this._div.appendChild(this._innerDiv);this._ether=bandInfo.ether;bandInfo.ether.initialize(timeline);this._etherPainter=bandInfo.etherPainter;bandInfo.etherPainter.initialize(this,timeline);this._eventSource=bandInfo.eventSource;if(this._eventSource){this._eventListener={onAddMany:function(){b._onAddMany();},onClear:function(){b._onClear();}}
this._eventSource.addListener(this._eventListener);}
this._eventPainter=bandInfo.eventPainter;bandInfo.eventPainter.initialize(this,timeline);this._decorators=("decorators"in bandInfo)?bandInfo.decorators:[];for(var i=0;i<this._decorators.length;i++){this._decorators[i].initialize(this,timeline);}
this._bubble=null;};Timeline._Band.SCROLL_MULTIPLES=5;Timeline._Band.prototype.dispose=function(){this.closeBubble();if(this._eventSource){this._eventSource.removeListener(this._eventListener);this._eventListener=null;this._eventSource=null;}
this._timeline=null;this._bandInfo=null;this._labeller=null;this._ether=null;this._etherPainter=null;this._eventPainter=null;this._decorators=null;this._onScrollListeners=null;this._syncWithBandHandler=null;this._selectorListener=null;this._div=null;this._innerDiv=null;this._keyboardInput=null;this._bubble=null;};Timeline._Band.prototype.addOnScrollListener=function(listener){this._onScrollListeners.push(listener);};Timeline._Band.prototype.removeOnScrollListener=function(listener){for(var i=0;i<this._onScrollListeners.length;i++){if(this._onScrollListeners[i]==listener){this._onScrollListeners.splice(i,1);break;}}};Timeline._Band.prototype.setSyncWithBand=function(band,highlight){if(this._syncWithBand){this._syncWithBand.removeOnScrollListener(this._syncWithBandHandler);}
this._syncWithBand=band;this._syncWithBand.addOnScrollListener(this._syncWithBandHandler);this._highlight=highlight;this._positionHighlight();};Timeline._Band.prototype.getLocale=function(){return this._locale;};Timeline._Band.prototype.getTimeZone=function(){return this._timeZone;};Timeline._Band.prototype.getLabeller=function(){return this._labeller;};Timeline._Band.prototype.getIndex=function(){return this._index;};Timeline._Band.prototype.getEther=function(){return this._ether;};Timeline._Band.prototype.getEtherPainter=function(){return this._etherPainter;};Timeline._Band.prototype.getEventSource=function(){return this._eventSource;};Timeline._Band.prototype.getEventPainter=function(){return this._eventPainter;};Timeline._Band.prototype.layout=function(){this.paint();};Timeline._Band.prototype.paint=function(){this._etherPainter.paint();this._paintDecorators();this._paintEvents();};Timeline._Band.prototype.softLayout=function(){this.softPaint();};Timeline._Band.prototype.softPaint=function(){this._etherPainter.softPaint();this._softPaintDecorators();this._softPaintEvents();};Timeline._Band.prototype.setBandShiftAndWidth=function(shift,width){var inputDiv=this._keyboardInput.parentNode;var middle=shift+Math.floor(width/2);if(this._timeline.isHorizontal()){this._div.style.top=shift+"px";this._div.style.height=width+"px";inputDiv.style.top=middle+"px";inputDiv.style.left="-1em";}else{this._div.style.left=shift+"px";this._div.style.width=width+"px";inputDiv.style.left=middle+"px";inputDiv.style.top="-1em";}};Timeline._Band.prototype.getViewWidth=function(){if(this._timeline.isHorizontal()){return this._div.offsetHeight;}else{return this._div.offsetWidth;}};Timeline._Band.prototype.setViewLength=function(length){this._viewLength=length;this._recenterDiv();this._onChanging();};Timeline._Band.prototype.getViewLength=function(){return this._viewLength;};Timeline._Band.prototype.getTotalViewLength=function(){return Timeline._Band.SCROLL_MULTIPLES*this._viewLength;};Timeline._Band.prototype.getViewOffset=function(){return this._viewOffset;};Timeline._Band.prototype.getMinDate=function(){return this._ether.pixelOffsetToDate(this._viewOffset);};Timeline._Band.prototype.getMaxDate=function(){return this._ether.pixelOffsetToDate(this._viewOffset+Timeline._Band.SCROLL_MULTIPLES*this._viewLength);};Timeline._Band.prototype.getMinVisibleDate=function(){return this._ether.pixelOffsetToDate(0);};Timeline._Band.prototype.getMaxVisibleDate=function(){return this._ether.pixelOffsetToDate(this._viewLength);};Timeline._Band.prototype.getCenterVisibleDate=function(){return this._ether.pixelOffsetToDate(this._viewLength/2);};Timeline._Band.prototype.setMinVisibleDate=function(date){if(!this._changing){this._moveEther(Math.round(-this._ether.dateToPixelOffset(date)));}};Timeline._Band.prototype.setMaxVisibleDate=function(date){if(!this._changing){this._moveEther(Math.round(this._viewLength-this._ether.dateToPixelOffset(date)));}};Timeline._Band.prototype.setCenterVisibleDate=function(date){if(!this._changing){this._moveEther(Math.round(this._viewLength/2-this._ether.dateToPixelOffset(date)));}};Timeline._Band.prototype.dateToPixelOffset=function(date){return this._ether.dateToPixelOffset(date)-this._viewOffset;};Timeline._Band.prototype.pixelOffsetToDate=function(pixels){return this._ether.pixelOffsetToDate(pixels+this._viewOffset);};Timeline._Band.prototype.createLayerDiv=function(zIndex){var div=this._timeline.getDocument().createElement("div");div.className="timeline-band-layer";div.style.zIndex=zIndex;this._innerDiv.appendChild(div);var innerDiv=this._timeline.getDocument().createElement("div");innerDiv.className="timeline-band-layer-inner";if(Timeline.Platform.browser.isIE){innerDiv.style.cursor="move";}else{innerDiv.style.cursor="-moz-grab";}
div.appendChild(innerDiv);return innerDiv;};Timeline._Band.prototype.removeLayerDiv=function(div){this._innerDiv.removeChild(div.parentNode);};Timeline._Band.prototype.closeBubble=function(){if(this._bubble!=null){this._bubble.close();this._bubble=null;}};Timeline._Band.prototype.openBubbleForPoint=function(pageX,pageY,width,height){this.closeBubble();this._bubble=Timeline.Graphics.createBubbleForPoint(this._timeline.getDocument(),pageX,pageY,width,height);return this._bubble.content;};Timeline._Band.prototype.scrollToCenter=function(date){var pixelOffset=this._ether.dateToPixelOffset(date);if(pixelOffset<-this._viewLength/2){this.setCenterVisibleDate(this.pixelOffsetToDate(pixelOffset+this._viewLength));}else if(pixelOffset>3*this._viewLength/2){this.setCenterVisibleDate(this.pixelOffsetToDate(pixelOffset-this._viewLength));}
this._autoScroll(Math.round(this._viewLength/2-this._ether.dateToPixelOffset(date)));};Timeline._Band.prototype._onMouseDown=function(innerFrame,evt,target){this.closeBubble();this._dragging=true;this._dragX=evt.clientX;this._dragY=evt.clientY;};Timeline._Band.prototype._onMouseMove=function(innerFrame,evt,target){if(this._dragging){var diffX=evt.clientX-this._dragX;var diffY=evt.clientY-this._dragY;this._dragX=evt.clientX;this._dragY=evt.clientY;this._moveEther(this._timeline.isHorizontal()?diffX:diffY);this._positionHighlight();}};Timeline._Band.prototype._onMouseUp=function(innerFrame,evt,target){this._dragging=false;this._keyboardInput.focus();};Timeline._Band.prototype._onMouseOut=function(innerFrame,evt,target){var coords=Timeline.DOM.getEventRelativeCoordinates(evt,innerFrame);coords.x+=this._viewOffset;if(coords.x<0||coords.x>innerFrame.offsetWidth||coords.y<0||coords.y>innerFrame.offsetHeight){this._dragging=false;}};Timeline._Band.prototype._onDblClick=function(innerFrame,evt,target){var coords=Timeline.DOM.getEventRelativeCoordinates(evt,innerFrame);var distance=coords.x-(this._viewLength/2-this._viewOffset);this._autoScroll(-distance);};Timeline._Band.prototype._onKeyDown=function(keyboardInput,evt,target){if(!this._dragging){switch(evt.keyCode){case 27:break;case 37:case 38:this._scrollSpeed=Math.min(50,Math.abs(this._scrollSpeed*1.05));this._moveEther(this._scrollSpeed);break;case 39:case 40:this._scrollSpeed=-Math.min(50,Math.abs(this._scrollSpeed*1.05));this._moveEther(this._scrollSpeed);break;default:return true;}
this.closeBubble();Timeline.DOM.cancelEvent(evt);return false;}
return true;};Timeline._Band.prototype._onKeyUp=function(keyboardInput,evt,target){if(!this._dragging){this._scrollSpeed=this._originalScrollSpeed;switch(evt.keyCode){case 35:this.setCenterVisibleDate(this._eventSource.getLatestDate());break;case 36:this.setCenterVisibleDate(this._eventSource.getEarliestDate());break;case 33:this._autoScroll(this._timeline.getPixelLength());break;case 34:this._autoScroll(-this._timeline.getPixelLength());break;default:return true;}
this.closeBubble();Timeline.DOM.cancelEvent(evt);return false;}
return true;};Timeline._Band.prototype._autoScroll=function(distance){var b=this;var a=Timeline.Graphics.createAnimation(function(abs,diff){b._moveEther(diff);},0,distance,1000);a.run();};Timeline._Band.prototype._moveEther=function(shift){this.closeBubble();this._viewOffset+=shift;this._ether.shiftPixels(-shift);if(this._timeline.isHorizontal()){this._div.style.left=this._viewOffset+"px";}else{this._div.style.top=this._viewOffset+"px";}
if(this._viewOffset>-this._viewLength*0.5||this._viewOffset<-this._viewLength*(Timeline._Band.SCROLL_MULTIPLES-1.5)){this._recenterDiv();}else{this.softLayout();}
this._onChanging();}
Timeline._Band.prototype._onChanging=function(){this._changing=true;this._fireOnScroll();this._setSyncWithBandDate();this._changing=false;};Timeline._Band.prototype._fireOnScroll=function(){for(var i=0;i<this._onScrollListeners.length;i++){this._onScrollListeners[i](this);}};Timeline._Band.prototype._setSyncWithBandDate=function(){if(this._syncWithBand){var centerDate=this._ether.pixelOffsetToDate(this.getViewLength()/2);this._syncWithBand.setCenterVisibleDate(centerDate);}};Timeline._Band.prototype._onHighlightBandScroll=function(){if(this._syncWithBand){var centerDate=this._syncWithBand.getCenterVisibleDate();var centerPixelOffset=this._ether.dateToPixelOffset(centerDate);this._moveEther(Math.round(this._viewLength/2-centerPixelOffset));if(this._highlight){this._etherPainter.setHighlight(this._syncWithBand.getMinVisibleDate(),this._syncWithBand.getMaxVisibleDate());}}};Timeline._Band.prototype._onAddMany=function(){this._paintEvents();};Timeline._Band.prototype._onClear=function(){this._paintEvents();};Timeline._Band.prototype._positionHighlight=function(){if(this._syncWithBand){var startDate=this._syncWithBand.getMinVisibleDate();var endDate=this._syncWithBand.getMaxVisibleDate();if(this._highlight){this._etherPainter.setHighlight(startDate,endDate);}}};Timeline._Band.prototype._recenterDiv=function(){this._viewOffset=-this._viewLength*(Timeline._Band.SCROLL_MULTIPLES-1)/2;if(this._timeline.isHorizontal()){this._div.style.left=this._viewOffset+"px";this._div.style.width=(Timeline._Band.SCROLL_MULTIPLES*this._viewLength)+"px";}else{this._div.style.top=this._viewOffset+"px";this._div.style.height=(Timeline._Band.SCROLL_MULTIPLES*this._viewLength)+"px";}
this.layout();};Timeline._Band.prototype._paintEvents=function(){this._eventPainter.paint();};Timeline._Band.prototype._softPaintEvents=function(){this._eventPainter.softPaint();};Timeline._Band.prototype._paintDecorators=function(){for(var i=0;i<this._decorators.length;i++){this._decorators[i].paint();}};Timeline._Band.prototype._softPaintDecorators=function(){for(var i=0;i<this._decorators.length;i++){this._decorators[i].softPaint();}};
/* platform.js */
Timeline.Platform.os={isMac:false,isWin:false,isWin32:false,isUnix:false};Timeline.Platform.browser={isIE:false,isNetscape:false,isMozilla:false,isFirefox:false,isOpera:false,isSafari:false,majorVersion:0,minorVersion:0};(function(){var an=navigator.appName.toLowerCase();var ua=navigator.userAgent.toLowerCase();Timeline.Platform.os.isMac=(ua.indexOf('mac')!=-1);Timeline.Platform.os.isWin=(ua.indexOf('win')!=-1);Timeline.Platform.os.isWin32=Timeline.Platform.isWin&&(ua.indexOf('95')!=-1||ua.indexOf('98')!=-1||ua.indexOf('nt')!=-1||ua.indexOf('win32')!=-1||ua.indexOf('32bit')!=-1);Timeline.Platform.os.isUnix=(ua.indexOf('x11')!=-1);Timeline.Platform.browser.isIE=(an.indexOf("microsoft")!=-1);Timeline.Platform.browser.isNetscape=(an.indexOf("netscape")!=-1);Timeline.Platform.browser.isMozilla=(ua.indexOf("mozilla")!=-1);Timeline.Platform.browser.isFirefox=(ua.indexOf("firefox")!=-1);Timeline.Platform.browser.isOpera=(an.indexOf("opera")!=-1);var parseVersionString=function(s){var a=s.split(".");Timeline.Platform.browser.majorVersion=parseInt(a[0]);Timeline.Platform.browser.minorVersion=parseInt(a[1]);};var indexOf=function(s,sub,start){var i=s.indexOf(sub,start);return i>=0?i:s.length;};if(Timeline.Platform.browser.isMozilla){var offset=ua.indexOf("mozilla/");if(offset>=0){parseVersionString(ua.substring(offset+8,indexOf(ua," ",offset)));}}
if(Timeline.Platform.browser.isIE){var offset=ua.indexOf("msie ");if(offset>=0){parseVersionString(ua.substring(offset+5,indexOf(ua,";",offset)));}}
if(Timeline.Platform.browser.isNetscape){var offset=ua.indexOf("rv:");if(offset>=0){parseVersionString(ua.substring(offset+3,indexOf(ua,")",offset)));}}
if(Timeline.Platform.browser.isFirefox){var offset=ua.indexOf("firefox/");if(offset>=0){parseVersionString(ua.substring(offset+8,indexOf(ua," ",offset)));}}})();Timeline.Platform.getDefaultLocale=function(){return Timeline.Platform.clientLocale;};
/* data-structure.js */
Timeline.SortedArray=function(compare,initialArray){this._a=(initialArray instanceof Array)?initialArray:[];this._compare=compare;};Timeline.SortedArray.prototype.add=function(elmt){var sa=this;var index=this.find(function(elmt2){return sa._compare(elmt2,elmt);});if(index<this._a.length){this._a.splice(index,0,elmt);}else{this._a.push(elmt);}};Timeline.SortedArray.prototype.remove=function(elmt){var sa=this;var index=this.find(function(elmt2){return sa._compare(elmt2,elmt);});while(index<this._a.length&&this._compare(this._a[index],elmt)==0){if(this._a[index]==elmt){this._a.splice(index,1);return true;}else{index++;}}
return false;};Timeline.SortedArray.prototype.removeAll=function(){this._a=[];};Timeline.SortedArray.prototype.elementAt=function(index){return this._a[index];};Timeline.SortedArray.prototype.length=function(){return this._a.length;};Timeline.SortedArray.prototype.find=function(compare){var a=0;var b=this._a.length;while(a<b){var mid=Math.floor((a+b)/2);var c=compare(this._a[mid]);if(mid==a){return c<0?a+1:a;}else if(c<0){a=mid;}else{b=mid;}}
return a;};Timeline.SortedArray.prototype.getFirst=function(){return(this._a.length>0)?this._a[0]:null;};Timeline.SortedArray.prototype.getLast=function(){return(this._a.length>0)?this._a[this._a.length-1]:null;};Timeline.EventIndex=function(unit){var eventIndex=this;this._unit=(unit!=null)?unit:Timeline.NativeDateUnit;this._events=new Timeline.SortedArray(function(event1,event2){return eventIndex._unit.compare(event1.getStart(),event2.getStart());});this._indexed=true;};Timeline.EventIndex.prototype.getUnit=function(){return this._unit;};Timeline.EventIndex.prototype.add=function(evt){this._events.add(evt);this._indexed=false;};Timeline.EventIndex.prototype.removeAll=function(){this._events.removeAll();this._indexed=false;};Timeline.EventIndex.prototype.getCount=function(){return this._events.length();};Timeline.EventIndex.prototype.getIterator=function(startDate,endDate){if(!this._indexed){this._index();}
return new Timeline.EventIndex._Iterator(this._events,startDate,endDate,this._unit);};Timeline.EventIndex.prototype.getAllIterator=function(){return new Timeline.EventIndex._AllIterator(this._events);};Timeline.EventIndex.prototype.getEarliestDate=function(){var evt=this._events.getFirst();return(evt==null)?null:evt.getStart();};Timeline.EventIndex.prototype.getLatestDate=function(){var evt=this._events.getLast();if(evt==null){return null;}
if(!this._indexed){this._index();}
var index=evt._earliestOverlapIndex;var date=this._events.elementAt(index).getEnd();for(var i=index+1;i<this._events.length();i++){date=this._unit.later(date,this._events.elementAt(i).getEnd());}
return date;};Timeline.EventIndex.prototype._index=function(){var l=this._events.length();for(var i=0;i<l;i++){var evt=this._events.elementAt(i);evt._earliestOverlapIndex=i;}
var toIndex=1;for(var i=0;i<l;i++){var evt=this._events.elementAt(i);var end=evt.getEnd();toIndex=Math.max(toIndex,i+1);while(toIndex<l){var evt2=this._events.elementAt(toIndex);var start2=evt2.getStart();if(this._unit.compare(start2,end)<0){evt2._earliestOverlapIndex=i;toIndex++;}else{break;}}}
this._indexed=true;};Timeline.EventIndex._Iterator=function(events,startDate,endDate,unit){this._events=events;this._startDate=startDate;this._endDate=endDate;this._unit=unit;this._currentIndex=events.find(function(evt){return unit.compare(evt.getStart(),startDate);});if(this._currentIndex-1>=0){this._currentIndex=this._events.elementAt(this._currentIndex-1)._earliestOverlapIndex;}
this._currentIndex--;this._maxIndex=events.find(function(evt){return unit.compare(evt.getStart(),endDate);});this._hasNext=false;this._next=null;this._findNext();};Timeline.EventIndex._Iterator.prototype={hasNext:function(){return this._hasNext;},next:function(){if(this._hasNext){var next=this._next;this._findNext();return next;}else{return null;}},_findNext:function(){var unit=this._unit;while((++this._currentIndex)<this._maxIndex){var evt=this._events.elementAt(this._currentIndex);if(unit.compare(evt.getStart(),this._endDate)<0&&unit.compare(evt.getEnd(),this._startDate)>0){this._next=evt;this._hasNext=true;return;}}
this._next=null;this._hasNext=false;}};Timeline.EventIndex._AllIterator=function(events){this._events=events;this._index=0;};Timeline.EventIndex._AllIterator.prototype={hasNext:function(){return this._index<this._events.length();},next:function(){return this._index<this._events.length()?this._events.elementAt(this._index++):null;}};
/* date-time.js */
Timeline.DateTime=new Object();Timeline.DateTime.MILLISECOND=0;Timeline.DateTime.SECOND=1;Timeline.DateTime.MINUTE=2;Timeline.DateTime.HOUR=3;Timeline.DateTime.DAY=4;Timeline.DateTime.WEEK=5;Timeline.DateTime.MONTH=6;Timeline.DateTime.YEAR=7;Timeline.DateTime.DECADE=8;Timeline.DateTime.CENTURY=9;Timeline.DateTime.MILLENNIUM=10;Timeline.DateTime.EPOCH=-1;Timeline.DateTime.ERA=-2;Timeline.DateTime.gregorianUnitLengths=[];(function(){var d=Timeline.DateTime;var a=d.gregorianUnitLengths;a[d.MILLISECOND]=1;a[d.SECOND]=1000;a[d.MINUTE]=a[d.SECOND]*60;a[d.HOUR]=a[d.MINUTE]*60;a[d.DAY]=a[d.HOUR]*24;a[d.WEEK]=a[d.DAY]*7;a[d.MONTH]=a[d.DAY]*31;a[d.YEAR]=a[d.DAY]*365;a[d.DECADE]=a[d.YEAR]*10;a[d.CENTURY]=a[d.YEAR]*100;a[d.MILLENNIUM]=a[d.YEAR]*1000;})();Timeline.DateTime.parseGregorianDateTime=function(o){if(o==null){return null;}else if(o instanceof Date){return o;}
var s=o.toString();if(s.length>0&&s.length<8){var space=s.indexOf(" ");if(space>0){var year=parseInt(s.substr(0,space));var suffix=s.substr(space+1);if(suffix.toLowerCase()=="bc"){year=1-year;}}else{var year=parseInt(s);}
var d=new Date(0);d.setUTCFullYear(year);return d;}
try{return new Date(Date.parse(s));}catch(e){return null;}};Timeline.DateTime._iso8601DateRegExp="^(-?)([0-9]{4})("+["(-?([0-9]{2})(-?([0-9]{2}))?)","(-?([0-9]{3}))","(-?W([0-9]{2})(-?([1-7]))?)"].join("|")+")?$";Timeline.DateTime.setIso8601Date=function(dateObject,string){var regexp=Timeline.DateTime._iso8601DateRegExp;var d=string.match(new RegExp(regexp));if(!d){throw new Error("Invalid date string: "+string);}
var sign=(d[1]=="-")?-1:1;var year=sign*d[2];var month=d[5];var date=d[7];var dayofyear=d[9];var week=d[11];var dayofweek=(d[13])?d[13]:1;dateObject.setUTCFullYear(year);if(dayofyear){dateObject.setUTCMonth(0);dateObject.setUTCDate(Number(dayofyear));}else if(week){dateObject.setUTCMonth(0);dateObject.setUTCDate(1);var gd=dateObject.getUTCDay();var day=(gd)?gd:7;var offset=Number(dayofweek)+(7*Number(week));if(day<=4){dateObject.setUTCDate(offset+1-day);}else{dateObject.setUTCDate(offset+8-day);}}else{if(month){dateObject.setUTCDate(1);dateObject.setUTCMonth(month-1);}
if(date){dateObject.setUTCDate(date);}}
return dateObject;};Timeline.DateTime.setIso8601Time=function(dateObject,string){var timezone="Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$";var d=string.match(new RegExp(timezone));var offset=0;if(d){if(d[0]!='Z'){offset=(Number(d[3])*60)+Number(d[5]);offset*=((d[2]=='-')?1:-1);}
string=string.substr(0,string.length-d[0].length);}
var regexp="^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(\.([0-9]+))?)?)?$";var d=string.match(new RegExp(regexp));if(!d){dojo.debug("invalid time string: "+string);return false;}
var hours=d[1];var mins=Number((d[3])?d[3]:0);var secs=(d[5])?d[5]:0;var ms=d[7]?(Number("0."+d[7])*1000):0;dateObject.setUTCHours(hours);dateObject.setUTCMinutes(mins);dateObject.setUTCSeconds(secs);dateObject.setUTCMilliseconds(ms);return dateObject;};Timeline.DateTime.setIso8601=function(dateObject,string){var comps=(string.indexOf("T")==-1)?string.split(" "):string.split("T");Timeline.DateTime.setIso8601Date(dateObject,comps[0]);if(comps.length==2){Timeline.DateTime.setIso8601Time(dateObject,comps[1]);}
return dateObject;};Timeline.DateTime.parseIso8601DateTime=function(string){try{return Timeline.DateTime.setIso8601(new Date(0),string);}catch(e){return null;}};Timeline.DateTime.roundDownToInterval=function(date,intervalUnit,timeZone,multiple,firstDayOfWeek){var timeShift=timeZone*Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.HOUR];var date2=new Date(date.getTime()+timeShift);var clearInDay=function(d){d.setUTCMilliseconds(0);d.setUTCSeconds(0);d.setUTCMinutes(0);d.setUTCHours(0);};var clearInYear=function(d){clearInDay(d);d.setUTCDate(1);d.setUTCMonth(0);};switch(intervalUnit){case Timeline.DateTime.MILLISECOND:var x=date2.getUTCMilliseconds();date2.setUTCMilliseconds(x-(x%multiple));break;case Timeline.DateTime.SECOND:date2.setUTCMilliseconds(0);var x=date2.getUTCSeconds();date2.setUTCSeconds(x-(x%multiple));break;case Timeline.DateTime.MINUTE:date2.setUTCMilliseconds(0);date2.setUTCSeconds(0);var x=date2.getUTCMinutes();date2.setTime(date2.getTime()-
(x%multiple)*Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.MINUTE]);break;case Timeline.DateTime.HOUR:date2.setUTCMilliseconds(0);date2.setUTCSeconds(0);date2.setUTCMinutes(0);var x=date2.getUTCHours();date2.setUTCHours(x-(x%multiple));break;case Timeline.DateTime.DAY:clearInDay(date2);break;case Timeline.DateTime.WEEK:clearInDay(date2);var d=(date2.getUTCDay()+7-firstDayOfWeek)%7;date2.setTime(date2.getTime()-
d*Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.DAY]);break;case Timeline.DateTime.MONTH:clearInDay(date2);date2.setUTCDate(1);var x=date2.getUTCMonth();date2.setUTCMonth(x-(x%multiple));break;case Timeline.DateTime.YEAR:clearInYear(date2);var x=date2.getUTCFullYear();date2.setUTCFullYear(x-(x%multiple));break;case Timeline.DateTime.DECADE:clearInYear(date2);date2.setUTCFullYear(Math.floor(date2.getUTCFullYear()/10)*10);break;case Timeline.DateTime.CENTURY:clearInYear(date2);date2.setUTCFullYear(Math.floor(date2.getUTCFullYear()/100)*100);break;case Timeline.DateTime.MILLENNIUM:clearInYear(date2);date2.setUTCFullYear(Math.floor(date2.getUTCFullYear()/1000)*1000);break;}
date.setTime(date2.getTime()-timeShift);};Timeline.DateTime.roundUpToInterval=function(date,intervalUnit,timeZone,multiple,firstDayOfWeek){var originalTime=date.getTime();Timeline.DateTime.roundDownToInterval(date,intervalUnit,timeZone,multiple,firstDayOfWeek);if(date.getTime()<originalTime){date.setTime(date.getTime()+
Timeline.DateTime.gregorianUnitLengths[intervalUnit]*multiple);}};Timeline.DateTime.incrementByInterval=function(date,intervalUnit){switch(intervalUnit){case Timeline.DateTime.MILLISECOND:date.setTime(date.getTime()+1)
break;case Timeline.DateTime.SECOND:date.setTime(date.getTime()+1000);break;case Timeline.DateTime.MINUTE:date.setTime(date.getTime()+
Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.MINUTE]);break;case Timeline.DateTime.HOUR:date.setTime(date.getTime()+
Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.HOUR]);break;case Timeline.DateTime.DAY:date.setUTCDate(date.getUTCDate()+1);break;case Timeline.DateTime.WEEK:date.setUTCDate(date.getUTCDate()+7);break;case Timeline.DateTime.MONTH:date.setUTCMonth(date.getUTCMonth()+1);break;case Timeline.DateTime.YEAR:date.setUTCFullYear(date.getUTCFullYear()+1);break;case Timeline.DateTime.DECADE:date.setUTCFullYear(date.getUTCFullYear()+10);break;case Timeline.DateTime.CENTURY:date.setUTCFullYear(date.getUTCFullYear()+100);break;case Timeline.DateTime.MILLENNIUM:date.setUTCFullYear(date.getUTCFullYear()+1000);break;}};Timeline.DateTime.removeTimeZoneOffset=function(date,timeZone){return new Date(date.getTime()+
timeZone*Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.HOUR]);};
/* debug.js */
Timeline.Debug=new Object();Timeline.Debug.log=function(msg){};Timeline.Debug.exception=function(e){alert("Caught exception: "+(Timeline.Platform.isIE?e.message:e));};
/* dom.js */
Timeline.DOM=new Object();Timeline.DOM.registerEventWithObject=function(elmt,eventName,obj,handler){Timeline.DOM.registerEvent(elmt,eventName,function(elmt2,evt,target){return handler.call(obj,elmt2,evt,target);});};Timeline.DOM.registerEvent=function(elmt,eventName,handler){var handler2=function(evt){evt=(evt)?evt:((event)?event:null);if(evt){var target=(evt.target)?evt.target:((evt.srcElement)?evt.srcElement:null);if(target){target=(target.nodeType==1||target.nodeType==9)?target:target.parentNode;}
return handler(elmt,evt,target);}
return true;}
if(Timeline.Platform.browser.isIE){elmt.attachEvent("on"+eventName,handler2);}else{elmt.addEventListener(eventName,handler2,false);}};Timeline.DOM.getPageCoordinates=function(elmt){var left=0;var top=0;if(elmt.nodeType!=1){elmt=elmt.parentNode;}
while(elmt!=null){left+=elmt.offsetLeft;top+=elmt.offsetTop;elmt=elmt.offsetParent;}
return{left:left,top:top};};Timeline.DOM.getEventRelativeCoordinates=function(evt,elmt){if(Timeline.Platform.browser.isIE){return{x:evt.offsetX,y:evt.offsetY};}else{var coords=Timeline.DOM.getPageCoordinates(elmt);return{x:evt.pageX-coords.left,y:evt.pageY-coords.top};}};Timeline.DOM.cancelEvent=function(evt){evt.returnValue=false;evt.cancelBubble=true;if("preventDefault"in evt){evt.preventDefault();}};
/* graphics.js */
Timeline.Graphics=new Object();Timeline.Graphics.pngIsTranslucent=(!Timeline.Platform.browser.isIE)||(Timeline.Platform.browser.majorVersion>6);Timeline.Graphics.createTranslucentImage=function(doc,url,verticalAlign){var elmt;if(Timeline.Graphics.pngIsTranslucent){elmt=doc.createElement("img");elmt.setAttribute("src",url);}else{elmt=doc.createElement("img");elmt.style.display="inline";elmt.style.width="1px";elmt.style.height="1px";elmt.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+url+"', sizingMethod='image')";}
elmt.style.verticalAlign=(verticalAlign!=null)?verticalAlign:"middle";return elmt;};Timeline.Graphics.setOpacity=function(elmt,opacity){if(Timeline.Platform.browser.isIE){elmt.style.filter="progid:DXImageTransform.Microsoft.Alpha(Style=0,Opacity="+opacity+")";}else{var o=(opacity/100).toString();elmt.style.opacity=o;elmt.style.MozOpacity=o;}};Timeline.Graphics._bubbleMargins={top:33,bottom:42,left:33,right:40}
Timeline.Graphics._arrowOffsets={top:0,bottom:9,left:1,right:8}
Timeline.Graphics._bubblePadding=15;Timeline.Graphics._bubblePointOffset=6;Timeline.Graphics._halfArrowWidth=18;Timeline.Graphics.createBubbleForPoint=function(doc,pageX,pageY,contentWidth,contentHeight){var bubble={_closed:false,_doc:doc,close:function(){if(!this._closed){this._doc.body.removeChild(this._div);this._doc=null;this._div=null;this._content=null;this._closed=true;}}};var docWidth=doc.body.offsetWidth;var docHeight=doc.body.offsetHeight;var margins=Timeline.Graphics._bubbleMargins;var bubbleWidth=margins.left+contentWidth+margins.right;var bubbleHeight=margins.top+contentHeight+margins.bottom;var pngIsTranslucent=Timeline.Graphics.pngIsTranslucent;var urlPrefix=Timeline.urlPrefix;var setImg=function(elmt,url,width,height){elmt.style.position="absolute";elmt.style.width=width+"px";elmt.style.height=height+"px";if(pngIsTranslucent){elmt.style.background="url("+url+")";}else{elmt.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+url+"', sizingMethod='crop')";}}
var div=doc.createElement("div");div.style.width=bubbleWidth+"px";div.style.height=bubbleHeight+"px";div.style.position="absolute";div.style.zIndex=1000;bubble._div=div;var divInner=doc.createElement("div");divInner.style.width="100%";divInner.style.height="100%";divInner.style.position="relative";div.appendChild(divInner);var createImg=function(url,left,top,width,height){var divImg=doc.createElement("div");divImg.style.left=left+"px";divImg.style.top=top+"px";setImg(divImg,url,width,height);divInner.appendChild(divImg);}
createImg(urlPrefix+"images/bubble-top-left.png",0,0,margins.left,margins.top);createImg(urlPrefix+"images/bubble-top.png",margins.left,0,contentWidth,margins.top);createImg(urlPrefix+"images/bubble-top-right.png",margins.left+contentWidth,0,margins.right,margins.top);createImg(urlPrefix+"images/bubble-left.png",0,margins.top,margins.left,contentHeight);createImg(urlPrefix+"images/bubble-right.png",margins.left+contentWidth,margins.top,margins.right,contentHeight);createImg(urlPrefix+"images/bubble-bottom-left.png",0,margins.top+contentHeight,margins.left,margins.bottom);createImg(urlPrefix+"images/bubble-bottom.png",margins.left,margins.top+contentHeight,contentWidth,margins.bottom);createImg(urlPrefix+"images/bubble-bottom-right.png",margins.left+contentWidth,margins.top+contentHeight,margins.right,margins.bottom);var divClose=doc.createElement("div");divClose.style.left=(bubbleWidth-margins.right+Timeline.Graphics._bubblePadding-16-2)+"px";divClose.style.top=(margins.top-Timeline.Graphics._bubblePadding+1)+"px";divClose.style.cursor="pointer";setImg(divClose,urlPrefix+"images/close-button.png",16,16);Timeline.DOM.registerEventWithObject(divClose,"click",bubble,bubble.close);divInner.appendChild(divClose);var divContent=doc.createElement("div");divContent.style.position="absolute";divContent.style.left=margins.left+"px";divContent.style.top=margins.top+"px";divContent.style.width=contentWidth+"px";divContent.style.height=contentHeight+"px";divContent.style.overflow="auto";divContent.style.background="white";divInner.appendChild(divContent);bubble.content=divContent;(function(){if(pageX-Timeline.Graphics._halfArrowWidth-Timeline.Graphics._bubblePadding>0&&pageX+Timeline.Graphics._halfArrowWidth+Timeline.Graphics._bubblePadding<docWidth){var left=pageX-Math.round(contentWidth/2)-margins.left;left=pageX<(docWidth/2)?Math.max(left,-(margins.left-Timeline.Graphics._bubblePadding)):Math.min(left,docWidth+(margins.right-Timeline.Graphics._bubblePadding)-bubbleWidth);if(pageY-Timeline.Graphics._bubblePointOffset-bubbleHeight>0){var divImg=doc.createElement("div");divImg.style.left=(pageX-Timeline.Graphics._halfArrowWidth-left)+"px";divImg.style.top=(margins.top+contentHeight)+"px";setImg(divImg,urlPrefix+"images/bubble-bottom-arrow.png",37,margins.bottom);divInner.appendChild(divImg);div.style.left=left+"px";div.style.top=(pageY-Timeline.Graphics._bubblePointOffset-bubbleHeight+
Timeline.Graphics._arrowOffsets.bottom)+"px";return;}else if(pageY+Timeline.Graphics._bubblePointOffset+bubbleHeight<docHeight){var divImg=doc.createElement("div");divImg.style.left=(pageX-Timeline.Graphics._halfArrowWidth-left)+"px";divImg.style.top="0px";setImg(divImg,urlPrefix+"images/bubble-top-arrow.png",37,margins.top);divInner.appendChild(divImg);div.style.left=left+"px";div.style.top=(pageY+Timeline.Graphics._bubblePointOffset-
Timeline.Graphics._arrowOffsets.top)+"px";return;}}
var top=pageY-Math.round(contentHeight/2)-margins.top;top=pageY<(docHeight/2)?Math.max(top,-(margins.top-Timeline.Graphics._bubblePadding)):Math.min(top,docHeight+(margins.bottom-Timeline.Graphics._bubblePadding)-bubbleHeight);if(pageX-Timeline.Graphics._bubblePointOffset-bubbleWidth>0){var divImg=doc.createElement("div");divImg.style.left=(margins.left+contentWidth)+"px";divImg.style.top=(pageY-Timeline.Graphics._halfArrowWidth-top)+"px";setImg(divImg,urlPrefix+"images/bubble-right-arrow.png",margins.right,37);divInner.appendChild(divImg);div.style.left=(pageX-Timeline.Graphics._bubblePointOffset-bubbleWidth+
Timeline.Graphics._arrowOffsets.right)+"px";div.style.top=top+"px";}else{var divImg=doc.createElement("div");divImg.style.left="0px";divImg.style.top=(pageY-Timeline.Graphics._halfArrowWidth-top)+"px";setImg(divImg,urlPrefix+"images/bubble-left-arrow.png",margins.left,37);divInner.appendChild(divImg);div.style.left=(pageX+Timeline.Graphics._bubblePointOffset-
Timeline.Graphics._arrowOffsets.left)+"px";div.style.top=top+"px";}})();doc.body.appendChild(div);return bubble;};Timeline.Graphics.createMessageBubble=function(doc){var containerDiv=doc.createElement("div");if(Timeline.Graphics.pngIsTranslucent){var topDiv=doc.createElement("div");topDiv.style.height="33px";topDiv.style.background="url("+Timeline.urlPrefix+"images/message-top-left.png) top left no-repeat";topDiv.style.paddingLeft="44px";containerDiv.appendChild(topDiv);var topRightDiv=doc.createElement("div");topRightDiv.style.height="33px";topRightDiv.style.background="url("+Timeline.urlPrefix+"images/message-top-right.png) top right no-repeat";topDiv.appendChild(topRightDiv);var middleDiv=doc.createElement("div");middleDiv.style.background="url("+Timeline.urlPrefix+"images/message-left.png) top left repeat-y";middleDiv.style.paddingLeft="44px";containerDiv.appendChild(middleDiv);var middleRightDiv=doc.createElement("div");middleRightDiv.style.background="url("+Timeline.urlPrefix+"images/message-right.png) top right repeat-y";middleRightDiv.style.paddingRight="44px";middleDiv.appendChild(middleRightDiv);var contentDiv=doc.createElement("div");middleRightDiv.appendChild(contentDiv);var bottomDiv=doc.createElement("div");bottomDiv.style.height="55px";bottomDiv.style.background="url("+Timeline.urlPrefix+"images/message-bottom-left.png) bottom left no-repeat";bottomDiv.style.paddingLeft="44px";containerDiv.appendChild(bottomDiv);var bottomRightDiv=doc.createElement("div");bottomRightDiv.style.height="55px";bottomRightDiv.style.background="url("+Timeline.urlPrefix+"images/message-bottom-right.png) bottom right no-repeat";bottomDiv.appendChild(bottomRightDiv);}else{containerDiv.style.border="2px solid #7777AA";containerDiv.style.padding="20px";containerDiv.style.background="white";Timeline.Graphics.setOpacity(containerDiv,90);var contentDiv=doc.createElement("div");containerDiv.appendChild(contentDiv);}
return{containerDiv:containerDiv,contentDiv:contentDiv};};Timeline.Graphics.createAnimation=function(f,from,to,duration){return new Timeline.Graphics._Animation(f,from,to,duration);};Timeline.Graphics._Animation=function(f,from,to,duration){this.f=f;this.from=from;this.to=to;this.current=from;this.duration=duration;this.start=new Date().getTime();this.timePassed=0;};Timeline.Graphics._Animation.prototype.run=function(){var a=this;window.setTimeout(function(){a.step();},100);};Timeline.Graphics._Animation.prototype.step=function(){this.timePassed+=100;var timePassedFraction=this.timePassed/this.duration;var parameterFraction=-Math.cos(timePassedFraction*Math.PI)/2+0.5;var current=parameterFraction*(this.to-this.from)+this.from;try{this.f(current,current-this.current);}catch(e){}
this.current=current;if(this.timePassed<this.duration){this.run();}};
/* html.js */
Timeline.HTML=new Object();Timeline.HTML._e2uHash={};(function(){e2uHash=Timeline.HTML._e2uHash;e2uHash['nbsp']='\u00A0[space]';e2uHash['iexcl']='\u00A1';e2uHash['cent']='\u00A2';e2uHash['pound']='\u00A3';e2uHash['curren']='\u00A4';e2uHash['yen']='\u00A5';e2uHash['brvbar']='\u00A6';e2uHash['sect']='\u00A7';e2uHash['uml']='\u00A8';e2uHash['copy']='\u00A9';e2uHash['ordf']='\u00AA';e2uHash['laquo']='\u00AB';e2uHash['not']='\u00AC';e2uHash['shy']='\u00AD';e2uHash['reg']='\u00AE';e2uHash['macr']='\u00AF';e2uHash['deg']='\u00B0';e2uHash['plusmn']='\u00B1';e2uHash['sup2']='\u00B2';e2uHash['sup3']='\u00B3';e2uHash['acute']='\u00B4';e2uHash['micro']='\u00B5';e2uHash['para']='\u00B6';e2uHash['middot']='\u00B7';e2uHash['cedil']='\u00B8';e2uHash['sup1']='\u00B9';e2uHash['ordm']='\u00BA';e2uHash['raquo']='\u00BB';e2uHash['frac14']='\u00BC';e2uHash['frac12']='\u00BD';e2uHash['frac34']='\u00BE';e2uHash['iquest']='\u00BF';e2uHash['Agrave']='\u00C0';e2uHash['Aacute']='\u00C1';e2uHash['Acirc']='\u00C2';e2uHash['Atilde']='\u00C3';e2uHash['Auml']='\u00C4';e2uHash['Aring']='\u00C5';e2uHash['AElig']='\u00C6';e2uHash['Ccedil']='\u00C7';e2uHash['Egrave']='\u00C8';e2uHash['Eacute']='\u00C9';e2uHash['Ecirc']='\u00CA';e2uHash['Euml']='\u00CB';e2uHash['Igrave']='\u00CC';e2uHash['Iacute']='\u00CD';e2uHash['Icirc']='\u00CE';e2uHash['Iuml']='\u00CF';e2uHash['ETH']='\u00D0';e2uHash['Ntilde']='\u00D1';e2uHash['Ograve']='\u00D2';e2uHash['Oacute']='\u00D3';e2uHash['Ocirc']='\u00D4';e2uHash['Otilde']='\u00D5';e2uHash['Ouml']='\u00D6';e2uHash['times']='\u00D7';e2uHash['Oslash']='\u00D8';e2uHash['Ugrave']='\u00D9';e2uHash['Uacute']='\u00DA';e2uHash['Ucirc']='\u00DB';e2uHash['Uuml']='\u00DC';e2uHash['Yacute']='\u00DD';e2uHash['THORN']='\u00DE';e2uHash['szlig']='\u00DF';e2uHash['agrave']='\u00E0';e2uHash['aacute']='\u00E1';e2uHash['acirc']='\u00E2';e2uHash['atilde']='\u00E3';e2uHash['auml']='\u00E4';e2uHash['aring']='\u00E5';e2uHash['aelig']='\u00E6';e2uHash['ccedil']='\u00E7';e2uHash['egrave']='\u00E8';e2uHash['eacute']='\u00E9';e2uHash['ecirc']='\u00EA';e2uHash['euml']='\u00EB';e2uHash['igrave']='\u00EC';e2uHash['iacute']='\u00ED';e2uHash['icirc']='\u00EE';e2uHash['iuml']='\u00EF';e2uHash['eth']='\u00F0';e2uHash['ntilde']='\u00F1';e2uHash['ograve']='\u00F2';e2uHash['oacute']='\u00F3';e2uHash['ocirc']='\u00F4';e2uHash['otilde']='\u00F5';e2uHash['ouml']='\u00F6';e2uHash['divide']='\u00F7';e2uHash['oslash']='\u00F8';e2uHash['ugrave']='\u00F9';e2uHash['uacute']='\u00FA';e2uHash['ucirc']='\u00FB';e2uHash['uuml']='\u00FC';e2uHash['yacute']='\u00FD';e2uHash['thorn']='\u00FE';e2uHash['yuml']='\u00FF';e2uHash['quot']='\u0022';e2uHash['amp']='\u0026';e2uHash['lt']='\u003C';e2uHash['gt']='\u003E';e2uHash['OElig']='';e2uHash['oelig']='\u0153';e2uHash['Scaron']='\u0160';e2uHash['scaron']='\u0161';e2uHash['Yuml']='\u0178';e2uHash['circ']='\u02C6';e2uHash['tilde']='\u02DC';e2uHash['ensp']='\u2002';e2uHash['emsp']='\u2003';e2uHash['thinsp']='\u2009';e2uHash['zwnj']='\u200C';e2uHash['zwj']='\u200D';e2uHash['lrm']='\u200E';e2uHash['rlm']='\u200F';e2uHash['ndash']='\u2013';e2uHash['mdash']='\u2014';e2uHash['lsquo']='\u2018';e2uHash['rsquo']='\u2019';e2uHash['sbquo']='\u201A';e2uHash['ldquo']='\u201C';e2uHash['rdquo']='\u201D';e2uHash['bdquo']='\u201E';e2uHash['dagger']='\u2020';e2uHash['Dagger']='\u2021';e2uHash['permil']='\u2030';e2uHash['lsaquo']='\u2039';e2uHash['rsaquo']='\u203A';e2uHash['euro']='\u20AC';e2uHash['fnof']='\u0192';e2uHash['Alpha']='\u0391';e2uHash['Beta']='\u0392';e2uHash['Gamma']='\u0393';e2uHash['Delta']='\u0394';e2uHash['Epsilon']='\u0395';e2uHash['Zeta']='\u0396';e2uHash['Eta']='\u0397';e2uHash['Theta']='\u0398';e2uHash['Iota']='\u0399';e2uHash['Kappa']='\u039A';e2uHash['Lambda']='\u039B';e2uHash['Mu']='\u039C';e2uHash['Nu']='\u039D';e2uHash['Xi']='\u039E';e2uHash['Omicron']='\u039F';e2uHash['Pi']='\u03A0';e2uHash['Rho']='\u03A1';e2uHash['Sigma']='\u03A3';e2uHash['Tau']='\u03A4';e2uHash['Upsilon']='\u03A5';e2uHash['Phi']='\u03A6';e2uHash['Chi']='\u03A7';e2uHash['Psi']='\u03A8';e2uHash['Omega']='\u03A9';e2uHash['alpha']='\u03B1';e2uHash['beta']='\u03B2';e2uHash['gamma']='\u03B3';e2uHash['delta']='\u03B4';e2uHash['epsilon']='\u03B5';e2uHash['zeta']='\u03B6';e2uHash['eta']='\u03B7';e2uHash['theta']='\u03B8';e2uHash['iota']='\u03B9';e2uHash['kappa']='\u03BA';e2uHash['lambda']='\u03BB';e2uHash['mu']='\u03BC';e2uHash['nu']='\u03BD';e2uHash['xi']='\u03BE';e2uHash['omicron']='\u03BF';e2uHash['pi']='\u03C0';e2uHash['rho']='\u03C1';e2uHash['sigmaf']='\u03C2';e2uHash['sigma']='\u03C3';e2uHash['tau']='\u03C4';e2uHash['upsilon']='\u03C5';e2uHash['phi']='\u03C6';e2uHash['chi']='\u03C7';e2uHash['psi']='\u03C8';e2uHash['omega']='\u03C9';e2uHash['thetasym']='\u03D1';e2uHash['upsih']='\u03D2';e2uHash['piv']='\u03D6';e2uHash['bull']='\u2022';e2uHash['hellip']='\u2026';e2uHash['prime']='\u2032';e2uHash['Prime']='\u2033';e2uHash['oline']='\u203E';e2uHash['frasl']='\u2044';e2uHash['weierp']='\u2118';e2uHash['image']='\u2111';e2uHash['real']='\u211C';e2uHash['trade']='\u2122';e2uHash['alefsym']='\u2135';e2uHash['larr']='\u2190';e2uHash['uarr']='\u2191';e2uHash['rarr']='\u2192';e2uHash['darr']='\u2193';e2uHash['harr']='\u2194';e2uHash['crarr']='\u21B5';e2uHash['lArr']='\u21D0';e2uHash['uArr']='\u21D1';e2uHash['rArr']='\u21D2';e2uHash['dArr']='\u21D3';e2uHash['hArr']='\u21D4';e2uHash['forall']='\u2200';e2uHash['part']='\u2202';e2uHash['exist']='\u2203';e2uHash['empty']='\u2205';e2uHash['nabla']='\u2207';e2uHash['isin']='\u2208';e2uHash['notin']='\u2209';e2uHash['ni']='\u220B';e2uHash['prod']='\u220F';e2uHash['sum']='\u2211';e2uHash['minus']='\u2212';e2uHash['lowast']='\u2217';e2uHash['radic']='\u221A';e2uHash['prop']='\u221D';e2uHash['infin']='\u221E';e2uHash['ang']='\u2220';e2uHash['and']='\u2227';e2uHash['or']='\u2228';e2uHash['cap']='\u2229';e2uHash['cup']='\u222A';e2uHash['int']='\u222B';e2uHash['there4']='\u2234';e2uHash['sim']='\u223C';e2uHash['cong']='\u2245';e2uHash['asymp']='\u2248';e2uHash['ne']='\u2260';e2uHash['equiv']='\u2261';e2uHash['le']='\u2264';e2uHash['ge']='\u2265';e2uHash['sub']='\u2282';e2uHash['sup']='\u2283';e2uHash['nsub']='\u2284';e2uHash['sube']='\u2286';e2uHash['supe']='\u2287';e2uHash['oplus']='\u2295';e2uHash['otimes']='\u2297';e2uHash['perp']='\u22A5';e2uHash['sdot']='\u22C5';e2uHash['lceil']='\u2308';e2uHash['rceil']='\u2309';e2uHash['lfloor']='\u230A';e2uHash['rfloor']='\u230B';e2uHash['lang']='\u2329';e2uHash['rang']='\u232A';e2uHash['loz']='\u25CA';e2uHash['spades']='\u2660';e2uHash['clubs']='\u2663';e2uHash['hearts']='\u2665';e2uHash['diams']='\u2666';})();Timeline.HTML.deEntify=function(s){e2uHash=Timeline.HTML._e2uHash;var re=/&(\w+?);/;while(re.test(s)){var m=s.match(re);s=s.replace(re,e2uHash[m[1]]);}
return s;};
/* xmlhttp.js */
Timeline.XmlHttp=new Object();Timeline.XmlHttp._onReadyStateChange=function(xmlhttp,fError,fDone){switch(xmlhttp.readyState){case 4:try{if(xmlhttp.status==0||xmlhttp.status==200){if(fDone){fDone(xmlhttp);}}else{if(fError){fError(xmlhttp.statusText,xmlhttp.status,xmlhttp);}}}catch(e){Timeline.Debug.exception(e);}
break;}};Timeline.XmlHttp._createRequest=function(){if(Timeline.Platform.browser.isIE){var programIDs=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];for(var i=0;i<programIDs.length;i++){try{var programID=programIDs[i];var f=function(){return new ActiveXObject(programID);};var o=f();Timeline.XmlHttp._createRequest=f;return o;}catch(e){}}
throw new Error("Failed to create an XMLHttpRequest object");}else{try{var f=function(){return new XMLHttpRequest();};var o=f();Timeline.XmlHttp._createRequest=f;return o;}catch(e){throw new Error("Failed to create an XMLHttpRequest object");}}};Timeline.XmlHttp.get=function(url,fError,fDone){var xmlhttp=Timeline.XmlHttp._createRequest();xmlhttp.open("GET",url,true);xmlhttp.onreadystatechange=function(){Timeline.XmlHttp._onReadyStateChange(xmlhttp,fError,fDone);};xmlhttp.send(null);};Timeline.XmlHttp.post=function(url,body,fError,fDone){var xmlhttp=Timeline.XmlHttp._createRequest();xmlhttp.open("POST",url,true);xmlhttp.onreadystatechange=function(){Timeline.XmlHttp._onReadyStateChange(xmlhttp,fError,fDone);};xmlhttp.send(body);};Timeline.XmlHttp._forceXML=function(xmlhttp){try{xmlhttp.overrideMimeType("text/xml");}catch(e){xmlhttp.setrequestheader("Content-Type","text/xml");}};
/* decorators.js */
Timeline.SpanHighlightDecorator=function(params){this._unit=("unit"in params)?params.unit:Timeline.NativeDateUnit;this._startDate=(typeof params.startDate=="string")?this._unit.parseFromObject(params.startDate):params.startDate;this._endDate=(typeof params.endDate=="string")?this._unit.parseFromObject(params.endDate):params.endDate;this._startLabel=params.startLabel;this._endLabel=params.endLabel;this._color=params.color;this._opacity=("opacity"in params)?params.opacity:100;};Timeline.SpanHighlightDecorator.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._layerDiv=null;};Timeline.SpanHighlightDecorator.prototype.paint=function(){if(this._layerDiv!=null){this._band.removeLayerDiv(this._layerDiv);}
this._layerDiv=this._band.createLayerDiv(10);this._layerDiv.setAttribute("name","span-highlight-decorator");this._layerDiv.style.display="none";var minDate=this._band.getMinDate();var maxDate=this._band.getMaxDate();if(this._unit.compare(this._startDate,maxDate)<0&&this._unit.compare(this._endDate,minDate)>0){minDate=this._unit.later(minDate,this._startDate);maxDate=this._unit.earlier(maxDate,this._endDate);var minPixel=this._band.dateToPixelOffset(minDate);var maxPixel=this._band.dateToPixelOffset(maxDate);var doc=this._timeline.getDocument();var createTable=function(){var table=doc.createElement("table");table.insertRow(0).insertCell(0);return table;};var div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";div.style.background=this._color;if(this._opacity<100){Timeline.Graphics.setOpacity(div,this._opacity);}
this._layerDiv.appendChild(div);var tableStartLabel=createTable();tableStartLabel.style.position="absolute";tableStartLabel.style.overflow="hidden";tableStartLabel.style.fontSize="300%";tableStartLabel.style.fontWeight="bold";tableStartLabel.style.color=this._color;tableStartLabel.rows[0].cells[0].innerHTML=this._startLabel;this._layerDiv.appendChild(tableStartLabel);var tableEndLabel=createTable();tableEndLabel.style.position="absolute";tableEndLabel.style.overflow="hidden";tableEndLabel.style.fontSize="300%";tableEndLabel.style.fontWeight="bold";tableEndLabel.style.color=this._color;tableEndLabel.rows[0].cells[0].innerHTML=this._endLabel;this._layerDiv.appendChild(tableEndLabel);if(this._timeline.isHorizontal()){div.style.left=minPixel+"px";div.style.width=(maxPixel-minPixel)+"px";div.style.top="0px";div.style.height="100%";tableStartLabel.style.right=(this._band.getTotalViewLength()-minPixel)+"px";tableStartLabel.style.width=(this._startLabel.length)+"em";tableStartLabel.style.top="0px";tableStartLabel.style.height="100%";tableStartLabel.style.textAlign="right";tableEndLabel.style.left=maxPixel+"px";tableEndLabel.style.width=(this._endLabel.length)+"em";tableEndLabel.style.top="0px";tableEndLabel.style.height="100%";}else{div.style.top=minPixel+"px";div.style.height=(maxPixel-minPixel)+"px";div.style.left="0px";div.style.width="100%";tableStartLabel.style.bottom=minPixel+"px";tableStartLabel.style.height="1.5px";tableStartLabel.style.left="0px";tableStartLabel.style.width="100%";tableEndLabel.style.top=maxPixel+"px";tableEndLabel.style.height="1.5px";tableEndLabel.style.left="0px";tableEndLabel.style.width="100%";}}
this._layerDiv.style.display="block";};Timeline.SpanHighlightDecorator.prototype.softPaint=function(){};Timeline.PointHighlightDecorator=function(params){this._unit=("unit"in params)?params.unit:Timeline.NativeDateUnit;this._date=(typeof params.date=="string")?this._unit.parseFromObject(params.date):params.date;this._width=("width"in params)?params.width:10;this._color=params.color;this._opacity=("opacity"in params)?params.opacity:100;};Timeline.PointHighlightDecorator.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._layerDiv=null;};Timeline.PointHighlightDecorator.prototype.paint=function(){if(this._layerDiv!=null){this._band.removeLayerDiv(this._layerDiv);}
this._layerDiv=this._band.createLayerDiv(10);this._layerDiv.setAttribute("name","span-highlight-decorator");this._layerDiv.style.display="none";var minDate=this._band.getMinDate();var maxDate=this._band.getMaxDate();if(this._unit.compare(this._date,maxDate)<0&&this._unit.compare(this._date,minDate)>0){var pixel=this._band.dateToPixelOffset(this._date);var minPixel=pixel-Math.round(this._width/2);var doc=this._timeline.getDocument();var div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";div.style.background=this._color;if(this._opacity<100){Timeline.Graphics.setOpacity(div,this._opacity);}
this._layerDiv.appendChild(div);if(this._timeline.isHorizontal()){div.style.left=minPixel+"px";div.style.width=this._width+"px";div.style.top="0px";div.style.height="100%";}else{div.style.top=minPixel+"px";div.style.height=this._width+"px";div.style.left="0px";div.style.width="100%";}}
this._layerDiv.style.display="block";};Timeline.PointHighlightDecorator.prototype.softPaint=function(){};
/* ether-painters.js */
Timeline.GregorianEtherPainter=function(params){this._params=params;this._theme=params.theme;this._unit=params.unit;this._multiple=("multiple"in params)?params.multiple:1;};Timeline.GregorianEtherPainter.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._backgroundLayer=band.createLayerDiv(0);this._backgroundLayer.setAttribute("name","ether-background");this._backgroundLayer.style.background=this._theme.ether.backgroundColors[band.getIndex()];this._markerLayer=null;this._lineLayer=null;var align=("align"in this._params&&this._params.align!=undefined)?this._params.align:this._theme.ether.interval.marker[timeline.isHorizontal()?"hAlign":"vAlign"];var showLine=("showLine"in this._params)?this._params.showLine:this._theme.ether.interval.line.show;this._intervalMarkerLayout=new Timeline.EtherIntervalMarkerLayout(this._timeline,this._band,this._theme,align,showLine);this._highlight=new Timeline.EtherHighlight(this._timeline,this._band,this._theme,this._backgroundLayer);}
Timeline.GregorianEtherPainter.prototype.setHighlight=function(startDate,endDate){this._highlight.position(startDate,endDate);}
Timeline.GregorianEtherPainter.prototype.paint=function(){if(this._markerLayer){this._band.removeLayerDiv(this._markerLayer);}
this._markerLayer=this._band.createLayerDiv(100);this._markerLayer.setAttribute("name","ether-markers");this._markerLayer.style.display="none";if(this._lineLayer){this._band.removeLayerDiv(this._lineLayer);}
this._lineLayer=this._band.createLayerDiv(1);this._lineLayer.setAttribute("name","ether-lines");this._lineLayer.style.display="none";var minDate=this._band.getMinDate();var maxDate=this._band.getMaxDate();var timeZone=this._band.getTimeZone();var labeller=this._band.getLabeller();Timeline.DateTime.roundDownToInterval(minDate,this._unit,timeZone,1,this._theme.firstDayOfWeek);var p=this;var incrementDate=function(date){for(var i=0;i<p._multiple;i++){Timeline.DateTime.incrementByInterval(date,p._unit);}};while(minDate.getTime()<maxDate.getTime()){this._intervalMarkerLayout.createIntervalMarker(minDate,labeller,this._unit,this._markerLayer,this._lineLayer);incrementDate(minDate);}
this._markerLayer.style.display="block";this._lineLayer.style.display="block";};Timeline.GregorianEtherPainter.prototype.softPaint=function(){};Timeline.HotZoneGregorianEtherPainter=function(params){this._params=params;this._theme=params.theme;this._zones=[{startTime:Number.NEGATIVE_INFINITY,endTime:Number.POSITIVE_INFINITY,unit:params.unit,multiple:1}];for(var i=0;i<params.zones.length;i++){var zone=params.zones[i];var zoneStart=Timeline.DateTime.parseGregorianDateTime(zone.start).getTime();var zoneEnd=Timeline.DateTime.parseGregorianDateTime(zone.end).getTime();for(var j=0;j<this._zones.length&&zoneEnd>zoneStart;j++){var zone2=this._zones[j];if(zoneStart<zone2.endTime){if(zoneStart>zone2.startTime){this._zones.splice(j,0,{startTime:zone2.startTime,endTime:zoneStart,unit:zone2.unit,multiple:zone2.multiple});j++;zone2.startTime=zoneStart;}
if(zoneEnd<zone2.endTime){this._zones.splice(j,0,{startTime:zoneStart,endTime:zoneEnd,unit:zone.unit,multiple:(zone.multiple)?zone.multiple:1});j++;zone2.startTime=zoneEnd;zoneStart=zoneEnd;}else{zone2.multiple=zone.multiple;zone2.unit=zone.unit;zoneStart=zone2.endTime;}}}}};Timeline.HotZoneGregorianEtherPainter.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._backgroundLayer=band.createLayerDiv(0);this._backgroundLayer.setAttribute("name","ether-background");this._backgroundLayer.style.background=this._theme.ether.backgroundColors[band.getIndex()];this._markerLayer=null;this._lineLayer=null;var align=("align"in this._params&&this._params.align!=undefined)?this._params.align:this._theme.ether.interval.marker[timeline.isHorizontal()?"hAlign":"vAlign"];var showLine=("showLine"in this._params)?this._params.showLine:this._theme.ether.interval.line.show;this._intervalMarkerLayout=new Timeline.EtherIntervalMarkerLayout(this._timeline,this._band,this._theme,align,showLine);this._highlight=new Timeline.EtherHighlight(this._timeline,this._band,this._theme,this._backgroundLayer);}
Timeline.HotZoneGregorianEtherPainter.prototype.setHighlight=function(startDate,endDate){this._highlight.position(startDate,endDate);}
Timeline.HotZoneGregorianEtherPainter.prototype.paint=function(){if(this._markerLayer){this._band.removeLayerDiv(this._markerLayer);}
this._markerLayer=this._band.createLayerDiv(100);this._markerLayer.setAttribute("name","ether-markers");this._markerLayer.style.display="none";if(this._lineLayer){this._band.removeLayerDiv(this._lineLayer);}
this._lineLayer=this._band.createLayerDiv(1);this._lineLayer.setAttribute("name","ether-lines");this._lineLayer.style.display="none";var minDate=this._band.getMinDate();var maxDate=this._band.getMaxDate();var timeZone=this._band.getTimeZone();var labeller=this._band.getLabeller();var p=this;var incrementDate=function(date,zone){for(var i=0;i<zone.multiple;i++){Timeline.DateTime.incrementByInterval(date,zone.unit);}};var zStart=0;while(zStart<this._zones.length){if(minDate.getTime()<this._zones[zStart].endTime){break;}
zStart++;}
var zEnd=this._zones.length-1;while(zEnd>=0){if(maxDate.getTime()>this._zones[zEnd].startTime){break;}
zEnd--;}
for(var z=zStart;z<=zEnd;z++){var zone=this._zones[z];var minDate2=new Date(Math.max(minDate.getTime(),zone.startTime));var maxDate2=new Date(Math.min(maxDate.getTime(),zone.endTime));Timeline.DateTime.roundDownToInterval(minDate2,zone.unit,timeZone,zone.multiple,this._theme.firstDayOfWeek);Timeline.DateTime.roundUpToInterval(maxDate2,zone.unit,timeZone,zone.multiple,this._theme.firstDayOfWeek);while(minDate2.getTime()<maxDate2.getTime()){this._intervalMarkerLayout.createIntervalMarker(minDate2,labeller,zone.unit,this._markerLayer,this._lineLayer);incrementDate(minDate2,zone);}}
this._markerLayer.style.display="block";this._lineLayer.style.display="block";};Timeline.HotZoneGregorianEtherPainter.prototype.softPaint=function(){};Timeline.YearCountEtherPainter=function(params){this._params=params;this._theme=params.theme;this._startDate=Timeline.DateTime.parseGregorianDateTime(params.startDate);this._multiple=("multiple"in params)?params.multiple:1;};Timeline.YearCountEtherPainter.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._backgroundLayer=band.createLayerDiv(0);this._backgroundLayer.setAttribute("name","ether-background");this._backgroundLayer.style.background=this._theme.ether.backgroundColors[band.getIndex()];this._markerLayer=null;this._lineLayer=null;var align=("align"in this._params)?this._params.align:this._theme.ether.interval.marker[timeline.isHorizontal()?"hAlign":"vAlign"];var showLine=("showLine"in this._params)?this._params.showLine:this._theme.ether.interval.line.show;this._intervalMarkerLayout=new Timeline.EtherIntervalMarkerLayout(this._timeline,this._band,this._theme,align,showLine);this._highlight=new Timeline.EtherHighlight(this._timeline,this._band,this._theme,this._backgroundLayer);};Timeline.YearCountEtherPainter.prototype.setHighlight=function(startDate,endDate){this._highlight.position(startDate,endDate);};Timeline.YearCountEtherPainter.prototype.paint=function(){if(this._markerLayer){this._band.removeLayerDiv(this._markerLayer);}
this._markerLayer=this._band.createLayerDiv(100);this._markerLayer.setAttribute("name","ether-markers");this._markerLayer.style.display="none";if(this._lineLayer){this._band.removeLayerDiv(this._lineLayer);}
this._lineLayer=this._band.createLayerDiv(1);this._lineLayer.setAttribute("name","ether-lines");this._lineLayer.style.display="none";var minDate=new Date(this._startDate.getTime());var maxDate=this._band.getMaxDate();var yearDiff=this._band.getMinDate().getUTCFullYear()-this._startDate.getUTCFullYear();minDate.setUTCFullYear(this._band.getMinDate().getUTCFullYear()-yearDiff%this._multiple);var p=this;var incrementDate=function(date){for(var i=0;i<p._multiple;i++){Timeline.DateTime.incrementByInterval(date,Timeline.DateTime.YEAR);}};var labeller={labelInterval:function(date,intervalUnit){var diff=date.getUTCFullYear()-p._startDate.getUTCFullYear();return{text:diff,emphasized:diff==0};}};while(minDate.getTime()<maxDate.getTime()){this._intervalMarkerLayout.createIntervalMarker(minDate,labeller,Timeline.DateTime.YEAR,this._markerLayer,this._lineLayer);incrementDate(minDate);}
this._markerLayer.style.display="block";this._lineLayer.style.display="block";};Timeline.YearCountEtherPainter.prototype.softPaint=function(){};Timeline.QuarterlyEtherPainter=function(params){this._params=params;this._theme=params.theme;this._startDate=Timeline.DateTime.parseGregorianDateTime(params.startDate);};Timeline.QuarterlyEtherPainter.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._backgroundLayer=band.createLayerDiv(0);this._backgroundLayer.setAttribute("name","ether-background");this._backgroundLayer.style.background=this._theme.ether.backgroundColors[band.getIndex()];this._markerLayer=null;this._lineLayer=null;var align=("align"in this._params)?this._params.align:this._theme.ether.interval.marker[timeline.isHorizontal()?"hAlign":"vAlign"];var showLine=("showLine"in this._params)?this._params.showLine:this._theme.ether.interval.line.show;this._intervalMarkerLayout=new Timeline.EtherIntervalMarkerLayout(this._timeline,this._band,this._theme,align,showLine);this._highlight=new Timeline.EtherHighlight(this._timeline,this._band,this._theme,this._backgroundLayer);};Timeline.QuarterlyEtherPainter.prototype.setHighlight=function(startDate,endDate){this._highlight.position(startDate,endDate);};Timeline.QuarterlyEtherPainter.prototype.paint=function(){if(this._markerLayer){this._band.removeLayerDiv(this._markerLayer);}
this._markerLayer=this._band.createLayerDiv(100);this._markerLayer.setAttribute("name","ether-markers");this._markerLayer.style.display="none";if(this._lineLayer){this._band.removeLayerDiv(this._lineLayer);}
this._lineLayer=this._band.createLayerDiv(1);this._lineLayer.setAttribute("name","ether-lines");this._lineLayer.style.display="none";var minDate=new Date(0);var maxDate=this._band.getMaxDate();minDate.setUTCFullYear(Math.max(this._startDate.getUTCFullYear(),this._band.getMinDate().getUTCFullYear()));minDate.setUTCMonth(this._startDate.getUTCMonth());var p=this;var incrementDate=function(date){date.setUTCMonth(date.getUTCMonth()+3);};var labeller={labelInterval:function(date,intervalUnit){var quarters=(4+(date.getUTCMonth()-p._startDate.getUTCMonth())/3)%4;if(quarters!=0){return{text:"Q"+(quarters+1),emphasized:false};}else{return{text:"Y"+(date.getUTCFullYear()-p._startDate.getUTCFullYear()+1),emphasized:true};}}};while(minDate.getTime()<maxDate.getTime()){this._intervalMarkerLayout.createIntervalMarker(minDate,labeller,Timeline.DateTime.YEAR,this._markerLayer,this._lineLayer);incrementDate(minDate);}
this._markerLayer.style.display="block";this._lineLayer.style.display="block";};Timeline.QuarterlyEtherPainter.prototype.softPaint=function(){};Timeline.EtherIntervalMarkerLayout=function(timeline,band,theme,align,showLine){var horizontal=timeline.isHorizontal();if(horizontal){if(align=="Top"){this.positionDiv=function(div,offset){div.style.left=offset+"px";div.style.top="0px";};}else{this.positionDiv=function(div,offset){div.style.left=offset+"px";div.style.bottom="0px";};}}else{if(align=="Left"){this.positionDiv=function(div,offset){div.style.top=offset+"px";div.style.left="0px";};}else{this.positionDiv=function(div,offset){div.style.top=offset+"px";div.style.right="0px";};}}
var markerTheme=theme.ether.interval.marker;var lineTheme=theme.ether.interval.line;var weekendTheme=theme.ether.interval.weekend;var stylePrefix=(horizontal?"h":"v")+align;var labelStyler=markerTheme[stylePrefix+"Styler"];var emphasizedLabelStyler=markerTheme[stylePrefix+"EmphasizedStyler"];var day=Timeline.DateTime.gregorianUnitLengths[Timeline.DateTime.DAY];this.createIntervalMarker=function(date,labeller,unit,markerDiv,lineDiv){var offset=Math.round(band.dateToPixelOffset(date));if(showLine&&unit!=Timeline.DateTime.WEEK){var divLine=timeline.getDocument().createElement("div");divLine.style.position="absolute";if(lineTheme.opacity<100){Timeline.Graphics.setOpacity(divLine,lineTheme.opacity);}
if(horizontal){divLine.style.borderLeft="1px solid "+lineTheme.color;divLine.style.left=offset+"px";divLine.style.width="1px";divLine.style.top="0px";divLine.style.height="100%";}else{divLine.style.borderTop="1px solid "+lineTheme.color;divLine.style.top=offset+"px";divLine.style.height="1px";divLine.style.left="0px";divLine.style.width="100%";}
lineDiv.appendChild(divLine);}
if(unit==Timeline.DateTime.WEEK){var firstDayOfWeek=theme.firstDayOfWeek;var saturday=new Date(date.getTime()+(6-firstDayOfWeek-7)*day);var monday=new Date(saturday.getTime()+2*day);var saturdayPixel=Math.round(band.dateToPixelOffset(saturday));var mondayPixel=Math.round(band.dateToPixelOffset(monday));var length=Math.max(1,mondayPixel-saturdayPixel);var divWeekend=timeline.getDocument().createElement("div");divWeekend.style.position="absolute";divWeekend.style.background=weekendTheme.color;if(weekendTheme.opacity<100){Timeline.Graphics.setOpacity(divWeekend,weekendTheme.opacity);}
if(horizontal){divWeekend.style.left=saturdayPixel+"px";divWeekend.style.width=length+"px";divWeekend.style.top="0px";divWeekend.style.height="100%";}else{divWeekend.style.top=saturdayPixel+"px";divWeekend.style.height=length+"px";divWeekend.style.left="0px";divWeekend.style.width="100%";}
lineDiv.appendChild(divWeekend);}
var label=labeller.labelInterval(date,unit);var div=timeline.getDocument().createElement("div");div.innerHTML=label.text;div.style.position="absolute";(label.emphasized?emphasizedLabelStyler:labelStyler)(div);this.positionDiv(div,offset);markerDiv.appendChild(div);return div;};};Timeline.EtherHighlight=function(timeline,band,theme,backgroundLayer){var horizontal=timeline.isHorizontal();this._highlightDiv=null;this._createHighlightDiv=function(){if(this._highlightDiv==null){this._highlightDiv=timeline.getDocument().createElement("div");this._highlightDiv.setAttribute("name","ether-highlight");this._highlightDiv.style.position="absolute";this._highlightDiv.style.background=theme.ether.highlightColor;var opacity=theme.ether.highlightOpacity;if(opacity<100){Timeline.Graphics.setOpacity(this._highlightDiv,opacity);}
backgroundLayer.appendChild(this._highlightDiv);}}
this.position=function(startDate,endDate){this._createHighlightDiv();var startPixel=Math.round(band.dateToPixelOffset(startDate));var endPixel=Math.round(band.dateToPixelOffset(endDate));var length=Math.max(endPixel-startPixel,3);if(horizontal){this._highlightDiv.style.left=startPixel+"px";this._highlightDiv.style.width=length+"px";this._highlightDiv.style.top="2px";this._highlightDiv.style.height=(band.getViewWidth()-4)+"px";}else{this._highlightDiv.style.top=startPixel+"px";this._highlightDiv.style.height=length+"px";this._highlightDiv.style.left="2px";this._highlightDiv.style.width=(band.getViewWidth()-4)+"px";}}};
/* ethers.js */
Timeline.LinearEther=function(params){this._params=params;this._interval=params.interval;this._pixelsPerInterval=params.pixelsPerInterval;};Timeline.LinearEther.prototype.initialize=function(timeline){this._timeline=timeline;this._unit=timeline.getUnit();if("startsOn"in this._params){this._start=this._unit.parseFromObject(this._params.startsOn);}else if("endsOn"in this._params){this._start=this._unit.parseFromObject(this._params.endsOn);this.shiftPixels(-this._timeline.getPixelLength());}else if("centersOn"in this._params){this._start=this._unit.parseFromObject(this._params.centersOn);this.shiftPixels(-this._timeline.getPixelLength()/2);}else{this._start=this._unit.makeDefaultValue();this.shiftPixels(-this._timeline.getPixelLength()/2);}};Timeline.LinearEther.prototype.setDate=function(date){this._start=this._unit.cloneValue(date);};Timeline.LinearEther.prototype.shiftPixels=function(pixels){var numeric=this._interval*pixels/this._pixelsPerInterval;this._start=this._unit.change(this._start,numeric);};Timeline.LinearEther.prototype.dateToPixelOffset=function(date){var numeric=this._unit.compare(date,this._start);return this._pixelsPerInterval*numeric/this._interval;};Timeline.LinearEther.prototype.pixelOffsetToDate=function(pixels){var numeric=pixels*this._interval/this._pixelsPerInterval;return this._unit.change(this._start,numeric);};Timeline.HotZoneEther=function(params){this._params=params;this._interval=params.interval;this._pixelsPerInterval=params.pixelsPerInterval;};Timeline.HotZoneEther.prototype.initialize=function(timeline){this._timeline=timeline;this._unit=timeline.getUnit();this._zones=[{startTime:Number.NEGATIVE_INFINITY,endTime:Number.POSITIVE_INFINITY,magnify:1}];var params=this._params;for(var i=0;i<params.zones.length;i++){var zone=params.zones[i];var zoneStart=this._unit.parseFromObject(zone.start);var zoneEnd=this._unit.parseFromObject(zone.end);for(var j=0;j<this._zones.length&&this._unit.compare(zoneEnd,zoneStart)>0;j++){var zone2=this._zones[j];if(this._unit.compare(zoneStart,zone2.endTime)<0){if(this._unit.compare(zoneStart,zone2.startTime)>0){this._zones.splice(j,0,{startTime:zone2.startTime,endTime:zoneStart,magnify:zone2.magnify});j++;zone2.startTime=zoneStart;}
if(this._unit.compare(zoneEnd,zone2.endTime)<0){this._zones.splice(j,0,{startTime:zoneStart,endTime:zoneEnd,magnify:zone.magnify*zone2.magnify});j++;zone2.startTime=zoneEnd;zoneStart=zoneEnd;}else{zone2.magnify*=zone.magnify;zoneStart=zone2.endTime;}}}}
if("startsOn"in this._params){this._start=this._unit.parseFromObject(this._params.startsOn);}else if("endsOn"in this._params){this._start=this._unit.parseFromObject(this._params.endsOn);this.shiftPixels(-this._timeline.getPixelLength());}else if("centersOn"in this._params){this._start=this._unit.parseFromObject(this._params.centersOn);this.shiftPixels(-this._timeline.getPixelLength()/2);}else{this._start=this._unit.makeDefaultValue();this.shiftPixels(-this._timeline.getPixelLength()/2);}};Timeline.HotZoneEther.prototype.setDate=function(date){this._start=this._unit.cloneValue(date);};Timeline.HotZoneEther.prototype.shiftPixels=function(pixels){this._start=this.pixelOffsetToDate(pixels);};Timeline.HotZoneEther.prototype.dateToPixelOffset=function(date){return this._dateDiffToPixelOffset(this._start,date);};Timeline.HotZoneEther.prototype.pixelOffsetToDate=function(pixels){return this._pixelOffsetToDate(pixels,this._start);};Timeline.HotZoneEther.prototype._dateDiffToPixelOffset=function(fromDate,toDate){var scale=this._getScale();var fromTime=fromDate;var toTime=toDate;var pixels=0;if(this._unit.compare(fromTime,toTime)<0){var z=0;while(z<this._zones.length){if(this._unit.compare(fromTime,this._zones[z].endTime)<0){break;}
z++;}
while(this._unit.compare(fromTime,toTime)<0){var zone=this._zones[z];var toTime2=this._unit.earlier(toTime,zone.endTime);pixels+=(this._unit.compare(toTime2,fromTime)/(scale/zone.magnify));fromTime=toTime2;z++;}}else{var z=this._zones.length-1;while(z>=0){if(this._unit.compare(fromTime,this._zones[z].startTime)>0){break;}
z--;}
while(this._unit.compare(fromTime,toTime)>0){var zone=this._zones[z];var toTime2=this._unit.later(toTime,zone.startTime);pixels+=(this._unit.compare(toTime2,fromTime)/(scale/zone.magnify));fromTime=toTime2;z--;}}
return pixels;};Timeline.HotZoneEther.prototype._pixelOffsetToDate=function(pixels,fromDate){var scale=this._getScale();var time=fromDate;if(pixels>0){var z=0;while(z<this._zones.length){if(this._unit.compare(time,this._zones[z].endTime)<0){break;}
z++;}
while(pixels>0){var zone=this._zones[z];var scale2=scale/zone.magnify;if(zone.endTime==Number.POSITIVE_INFINITY){time=this._unit.change(time,pixels*scale2);pixels=0;}else{var pixels2=this._unit.compare(zone.endTime,time)/scale2;if(pixels2>pixels){time=this._unit.change(time,pixels*scale2);pixels=0;}else{time=zone.endTime;pixels-=pixels2;}}
z++;}}else{var z=this._zones.length-1;while(z>=0){if(this._unit.compare(time,this._zones[z].startTime)>0){break;}
z--;}
pixels=-pixels;while(pixels>0){var zone=this._zones[z];var scale2=scale/zone.magnify;if(zone.startTime==Number.NEGATIVE_INFINITY){time=this._unit.change(time,-pixels*scale2);pixels=0;}else{var pixels2=this._unit.compare(time,zone.startTime)/scale2;if(pixels2>pixels){time=this._unit.change(time,-pixels*scale2);pixels=0;}else{time=zone.startTime;pixels-=pixels2;}}
z--;}}
return time;};Timeline.HotZoneEther.prototype._getScale=function(){return this._interval/this._pixelsPerInterval;};
/* labellers.js */
Timeline.GregorianDateLabeller=function(locale,timeZone){this._locale=locale;this._timeZone=timeZone;};Timeline.GregorianDateLabeller.monthNames=[];Timeline.GregorianDateLabeller.dayNames=[];Timeline.GregorianDateLabeller.labelIntervalFunctions=[];Timeline.GregorianDateLabeller.getMonthName=function(month,locale){return Timeline.GregorianDateLabeller.monthNames[locale][month];};Timeline.GregorianDateLabeller.prototype.labelInterval=function(date,intervalUnit){var f=Timeline.GregorianDateLabeller.labelIntervalFunctions[this._locale];if(f==null){f=Timeline.GregorianDateLabeller.prototype.defaultLabelInterval;}
return f.call(this,date,intervalUnit);};Timeline.GregorianDateLabeller.prototype.labelPrecise=function(date){return Timeline.DateTime.removeTimeZoneOffset(date,this._timeZone).toUTCString();};Timeline.GregorianDateLabeller.prototype.defaultLabelInterval=function(date,intervalUnit){var text;var emphasized=false;date=Timeline.DateTime.removeTimeZoneOffset(date,this._timeZone);switch(intervalUnit){case Timeline.DateTime.MILLISECOND:text=date.getUTCMilliseconds();break;case Timeline.DateTime.SECOND:text=date.getUTCSeconds();break;case Timeline.DateTime.MINUTE:var m=date.getUTCMinutes();if(m==0){text=date.getUTCHours()+":00";emphasized=true;}else{text=m;}
break;case Timeline.DateTime.HOUR:text=date.getUTCHours()+"hr";break;case Timeline.DateTime.DAY:text=Timeline.GregorianDateLabeller.getMonthName(date.getUTCMonth(),this._locale)+" "+date.getUTCDate();break;case Timeline.DateTime.WEEK:text=Timeline.GregorianDateLabeller.getMonthName(date.getUTCMonth(),this._locale)+" "+date.getUTCDate();break;case Timeline.DateTime.MONTH:var m=date.getUTCMonth();if(m!=0){text=Timeline.GregorianDateLabeller.getMonthName(m,this._locale);break;}
case Timeline.DateTime.YEAR:case Timeline.DateTime.DECADE:case Timeline.DateTime.CENTURY:case Timeline.DateTime.MILLENNIUM:var y=date.getUTCFullYear();if(y>0){text=date.getUTCFullYear();}else{text=(1-y)+"BC";}
emphasized=(intervalUnit==Timeline.DateTime.MONTH)||(intervalUnit==Timeline.DateTime.DECADE&&y%100==0)||(intervalUnit==Timeline.DateTime.CENTURY&&y%1000==0);break;default:text=date.toUTCString();}
return{text:text,emphasized:emphasized};}
/* layouts.js */
Timeline.StaticTrackBasedLayout=function(params){this._eventSource=params.eventSource;this._ether=params.ether;this._theme=params.theme;this._showText=("showText"in params)?params.showText:true;this._laidout=false;var layout=this;if(this._eventSource!=null){this._eventSource.addListener({onAddMany:function(){layout._laidout=false;}});}};Timeline.StaticTrackBasedLayout.prototype.initialize=function(timeline){this._timeline=timeline;};Timeline.StaticTrackBasedLayout.prototype.getTrack=function(evt){if(!this._laidout){this._tracks=[];this._layout();this._laidout=true;}
return this._tracks[evt.getID()];};Timeline.StaticTrackBasedLayout.prototype.getTrackCount=function(){if(!this._laidout){this._tracks=[];this._layout();this._laidout=true;}
return this._trackCount;};Timeline.StaticTrackBasedLayout.prototype._layout=function(){if(this._eventSource==null){return;}
var streams=[Number.NEGATIVE_INFINITY];var layout=this;var showText=this._showText;var theme=this._theme;var eventTheme=theme.event;var layoutInstant=function(evt,startPixel,endPixel,streamOffset){var finalPixel=startPixel-1;if(evt.isImprecise()){finalPixel=endPixel;}
if(showText){finalPixel=Math.max(finalPixel,startPixel+eventTheme.label.width);}
return finalPixel;};var layoutDuration=function(evt,startPixel,endPixel,streamOffset){if(evt.isImprecise()){var startDate=evt.getStart();var endDate=evt.getEnd();var startPixel2=Math.round(layout._ether.dateToPixelOffset(startDate));var endPixel2=Math.round(layout._ether.dateToPixelOffset(endDate));}else{var startPixel2=startPixel;var endPixel2=endPixel;}
var finalPixel=endPixel2;var length=Math.max(endPixel2-startPixel2,1);if(showText){if(length<eventTheme.label.width){finalPixel=endPixel2+eventTheme.label.width;}}
return finalPixel;};var layoutEvent=function(evt){var startDate=evt.getStart();var endDate=evt.getEnd();var startPixel=Math.round(layout._ether.dateToPixelOffset(startDate));var endPixel=Math.round(layout._ether.dateToPixelOffset(endDate));var streamIndex=0;for(;streamIndex<streams.length;streamIndex++){if(streams[streamIndex]<startPixel){break;}}
if(streamIndex>=streams.length){streams.push(Number.NEGATIVE_INFINITY);}
var streamOffset=(eventTheme.track.offset+
streamIndex*(eventTheme.track.height+eventTheme.track.gap))+"em";layout._tracks[evt.getID()]=streamIndex;if(evt.isInstant()){streams[streamIndex]=layoutInstant(evt,startPixel,endPixel,streamOffset);}else{streams[streamIndex]=layoutDuration(evt,startPixel,endPixel,streamOffset);}};var iterator=this._eventSource.getAllEventIterator();while(iterator.hasNext()){var evt=iterator.next();layoutEvent(evt);}
this._trackCount=streams.length;};
/* painters.js */
Timeline.DurationEventPainter=function(params){this._params=params;this._theme=params.theme;this._layout=params.layout;this._showText=params.showText;this._showLineForNoText=("showLineForNoText"in params)?params.showLineForNoText:params.theme.event.instant.showLineForNoText;this._filterMatcher=null;this._highlightMatcher=null;};Timeline.DurationEventPainter.prototype.initialize=function(band,timeline){this._band=band;this._timeline=timeline;this._layout.initialize(band,timeline);this._eventLayer=null;this._highlightLayer=null;};Timeline.DurationEventPainter.prototype.getLayout=function(){return this._layout;};Timeline.DurationEventPainter.prototype.setLayout=function(layout){this._layout=layout;};Timeline.DurationEventPainter.prototype.getFilterMatcher=function(){return this._filterMatcher;};Timeline.DurationEventPainter.prototype.setFilterMatcher=function(filterMatcher){this._filterMatcher=filterMatcher;};Timeline.DurationEventPainter.prototype.getHighlightMatcher=function(){return this._highlightMatcher;};Timeline.DurationEventPainter.prototype.setHighlightMatcher=function(highlightMatcher){this._highlightMatcher=highlightMatcher;};Timeline.DurationEventPainter.prototype.paint=function(){var eventSource=this._band.getEventSource();if(eventSource==null){return;}
if(this._highlightLayer!=null){this._band.removeLayerDiv(this._highlightLayer);}
this._highlightLayer=this._band.createLayerDiv(105);this._highlightLayer.setAttribute("name","event-highlights");this._highlightLayer.style.display="none";if(this._eventLayer!=null){this._band.removeLayerDiv(this._eventLayer);}
this._eventLayer=this._band.createLayerDiv(110);this._eventLayer.setAttribute("name","events");this._eventLayer.style.display="none";var minDate=this._band.getMinDate();var maxDate=this._band.getMaxDate();var doc=this._timeline.getDocument();var p=this;var eventLayer=this._eventLayer;var highlightLayer=this._highlightLayer;var showText=this._showText;var theme=this._params.theme;var eventTheme=theme.event;var trackOffset=eventTheme.track.offset;var trackHeight=("trackHeight"in this._params)?this._params.trackHeight:eventTheme.track.height;var trackGap=("trackGap"in this._params)?this._params.trackGap:eventTheme.track.gap;var appendIcon=function(evt,div){var icon=evt.getIcon();var img=Timeline.Graphics.createTranslucentImage(doc,icon!=null?icon:eventTheme.instant.icon);div.appendChild(img);div.style.cursor="pointer";Timeline.DOM.registerEvent(div,"mousedown",function(elmt,domEvt,target){p._onClickInstantEvent(img,domEvt,evt);});};var createHighlightDiv=function(highlightIndex,startPixel,length,highlightOffset,highlightWidth){if(highlightIndex>=0){var color=eventTheme.highlightColors[Math.min(highlightIndex,eventTheme.highlightColors.length-1)];var div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";div.style.left=(startPixel-3)+"px";div.style.width=(length+6)+"px";div.style.top=highlightOffset+"em";div.style.height=highlightWidth+"em";div.style.background=color;highlightLayer.appendChild(div);}};var createInstantDiv=function(evt,startPixel,endPixel,streamOffset,highlightIndex,highlightOffset,highlightWidth){if(evt.isImprecise()){var length=Math.max(endPixel-startPixel,1);var divImprecise=doc.createElement("div");divImprecise.style.position="absolute";divImprecise.style.overflow="hidden";divImprecise.style.top=streamOffset;divImprecise.style.height=trackHeight+"em";divImprecise.style.left=startPixel+"px";divImprecise.style.width=length+"px";divImprecise.style.background=eventTheme.instant.impreciseColor;if(eventTheme.instant.impreciseOpacity<100){Timeline.Graphics.setOpacity(divImprecise,eventTheme.instant.impreciseOpacity);}
eventLayer.appendChild(divImprecise);}
var div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";eventLayer.appendChild(div);var foreground=evt.getTextColor();var background=evt.getColor();var realign=-8;var length=16;if(showText){div.style.width=eventTheme.label.width+"px";div.style.color=foreground!=null?foreground:eventTheme.label.outsideColor;appendIcon(evt,div);div.appendChild(doc.createTextNode(evt.getText()));}else{if(p._showLineForNoText){div.style.width="1px";div.style.borderLeft="1px solid "+(background!=null?background:eventTheme.instant.lineColor);realign=0;length=1;}else{appendIcon(evt,div);}}
div.style.top=streamOffset;div.style.height=trackHeight+"em";div.style.left=(startPixel+realign)+"px";createHighlightDiv(highlightIndex,(startPixel+realign),length,highlightOffset,highlightWidth);};var createDurationDiv=function(evt,startPixel,endPixel,streamOffset,highlightIndex,highlightOffset,highlightWidth){var attachClickEvent=function(elmt){elmt.style.cursor="pointer";Timeline.DOM.registerEvent(elmt,"mousedown",function(elmt,domEvt,target){p._onClickDurationEvent(domEvt,evt,target);});};var length=Math.max(endPixel-startPixel,1);if(evt.isImprecise()){var div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";div.style.top=streamOffset;div.style.height=trackHeight+"em";div.style.left=startPixel+"px";div.style.width=length+"px";div.style.background=eventTheme.duration.impreciseColor;if(eventTheme.duration.impreciseOpacity<100){Timeline.Graphics.setOpacity(div,eventTheme.duration.impreciseOpacity);}
eventLayer.appendChild(div);var startDate=evt.getLatestStart();var endDate=evt.getEarliestEnd();var startPixel2=Math.round(p._band.dateToPixelOffset(startDate));var endPixel2=Math.round(p._band.dateToPixelOffset(endDate));}else{var startPixel2=startPixel;var endPixel2=endPixel;}
var foreground=evt.getTextColor();var outside=true;if(startPixel2<=endPixel2){length=Math.max(endPixel2-startPixel2,1);outside=!(length>eventTheme.label.width);div=doc.createElement("div");div.style.position="absolute";div.style.overflow="hidden";div.style.top=streamOffset;div.style.height=trackHeight+"em";div.style.left=startPixel2+"px";div.style.width=length+"px";var background=evt.getColor();div.style.background=background!=null?background:eventTheme.duration.color;if(eventTheme.duration.opacity<100){Timeline.Graphics.setOpacity(div,eventTheme.duration.opacity);}
eventLayer.appendChild(div);}else{var temp=startPixel2;startPixel2=endPixel2;endPixel2=temp;}
if(div==null){console.log(evt);}
attachClickEvent(div);if(showText){var divLabel=doc.createElement("div");divLabel.style.position="absolute";divLabel.style.top=streamOffset;divLabel.style.height=trackHeight+"em";divLabel.style.left=((length>eventTheme.label.width)?startPixel2:endPixel2)+"px";divLabel.style.width=eventTheme.label.width+"px";divLabel.style.color=foreground!=null?foreground:(outside?eventTheme.label.outsideColor:eventTheme.label.insideColor);divLabel.style.overflow="hidden";divLabel.appendChild(doc.createTextNode(evt.getText()));eventLayer.appendChild(divLabel);attachClickEvent(divLabel);}
createHighlightDiv(highlightIndex,startPixel,endPixel-startPixel,highlightOffset,highlightWidth);};var createEventDiv=function(evt,highlightIndex){var startDate=evt.getStart();var endDate=evt.getEnd();var startPixel=Math.round(p._band.dateToPixelOffset(startDate));var endPixel=Math.round(p._band.dateToPixelOffset(endDate));var streamOffset=(trackOffset+
p._layout.getTrack(evt)*(trackHeight+trackGap));if(evt.isInstant()){createInstantDiv(evt,startPixel,endPixel,streamOffset+"em",highlightIndex,streamOffset-trackGap,trackHeight+2*trackGap);}else{createDurationDiv(evt,startPixel,endPixel,streamOffset+"em",highlightIndex,streamOffset-trackGap,trackHeight+2*trackGap);}};var filterMatcher=(this._filterMatcher!=null)?this._filterMatcher:function(evt){return true;};var highlightMatcher=(this._highlightMatcher!=null)?this._highlightMatcher:function(evt){return-1;};var iterator=eventSource.getEventIterator(minDate,maxDate);while(iterator.hasNext()){var evt=iterator.next();if(filterMatcher(evt)){createEventDiv(evt,highlightMatcher(evt));}}
this._highlightLayer.style.display="block";this._eventLayer.style.display="block";};Timeline.DurationEventPainter.prototype.softPaint=function(){};Timeline.DurationEventPainter.prototype._onClickInstantEvent=function(icon,domEvt,evt){domEvt.cancelBubble=true;var c=Timeline.DOM.getPageCoordinates(icon);this._showBubble(c.left+Math.ceil(icon.offsetWidth/2),c.top+Math.ceil(icon.offsetHeight/2),evt);};Timeline.DurationEventPainter.prototype._onClickDurationEvent=function(domEvt,evt,target){domEvt.cancelBubble=true;if("pageX"in domEvt){var x=domEvt.pageX;var y=domEvt.pageY;}else{var c=Timeline.DOM.getPageCoordinates(target);var x=domEvt.offsetX+c.left;var y=domEvt.offsetY+c.top;}
this._showBubble(x,y,evt);};Timeline.DurationEventPainter.prototype._showBubble=function(x,y,evt){var div=this._band.openBubbleForPoint(x,y,this._theme.event.bubble.width,this._theme.event.bubble.height);evt.fillInfoBubble(div,this._theme,this._band.getLabeller());};
/* sources.js */
Timeline.DefaultEventSource=function(eventIndex){this._events=(eventIndex instanceof Object)?eventIndex:new Timeline.EventIndex();this._listeners=[];};Timeline.DefaultEventSource.prototype.addListener=function(listener){this._listeners.push(listener);};Timeline.DefaultEventSource.prototype.removeListener=function(listener){for(var i=0;i<this._listeners.length;i++){if(this._listeners[i]==listener){this._listeners.splice(i,1);break;}}};Timeline.DefaultEventSource.prototype.loadXML=function(xml,url){var base=this._getBaseURL(url);var wikiURL=xml.documentElement.getAttribute("wiki-url");var wikiSection=xml.documentElement.getAttribute("wiki-section");var dateTimeFormat=xml.documentElement.getAttribute("date-time-format");var parseDateTimeFunction=this._events.getUnit().getParser(dateTimeFormat);var node=xml.documentElement.firstChild;var added=false;while(node!=null){if(node.nodeType==1){var description="";if(node.firstChild!=null&&node.firstChild.nodeType==3){description=node.firstChild.nodeValue;}
var evt=new Timeline.DefaultEventSource.Event(parseDateTimeFunction(node.getAttribute("start")),parseDateTimeFunction(node.getAttribute("end")),parseDateTimeFunction(node.getAttribute("latestStart")),parseDateTimeFunction(node.getAttribute("earliestEnd")),node.getAttribute("isDuration")!="true",node.getAttribute("title"),description,this._resolveRelativeURL(node.getAttribute("image"),base),this._resolveRelativeURL(node.getAttribute("link"),base),this._resolveRelativeURL(node.getAttribute("icon"),base),node.getAttribute("color"),node.getAttribute("textColor"));evt._node=node;evt.getProperty=function(name){return this._node.getAttribute(name);};evt.setWikiInfo(wikiURL,wikiSection);this._events.add(evt);added=true;}
node=node.nextSibling;}
if(added){this._fire("onAddMany",[]);}};Timeline.DefaultEventSource.prototype.loadJSON=function(data,url){var base=this._getBaseURL(url);var added=false;if(data&&data.events){var wikiURL=("wikiURL"in data)?data.wikiURL:null;var wikiSection=("wikiSection"in data)?data.wikiSection:null;var dateTimeFormat=("dateTimeFormat"in data)?data.dateTimeFormat:null;var parseDateTimeFunction=this._events.getUnit().getParser(dateTimeFormat);for(var i=0;i<data.events.length;i++){var event=data.events[i];var evt=new Timeline.DefaultEventSource.Event(parseDateTimeFunction(event.start),parseDateTimeFunction(event.end),parseDateTimeFunction(event.latestStart),parseDateTimeFunction(event.earliestEnd),event.isDuration||false,event.title,event.description,this._resolveRelativeURL(event.image,base),this._resolveRelativeURL(event.link,base),this._resolveRelativeURL(event.icon,base),event.color,event.textColor);evt._obj=event;evt.getProperty=function(name){return this._obj[name];};evt.setWikiInfo(wikiURL,wikiSection);this._events.add(evt);added=true;}}
if(added){this._fire("onAddMany",[]);}};Timeline.DefaultEventSource.prototype.loadSPARQL=function(xml,url){var base=this._getBaseURL(url);var dateTimeFormat='iso8601';var parseDateTimeFunction=this._events.getUnit().getParser(dateTimeFormat);if(xml==null){return;}
var node=xml.documentElement.firstChild;while(node!=null&&(node.nodeType!=1||node.nodeName!='results')){node=node.nextSibling;}
var wikiURL=null;var wikiSection=null;if(node!=null){wikiURL=node.getAttribute("wiki-url");wikiSection=node.getAttribute("wiki-section");node=node.firstChild;}
var added=false;while(node!=null){if(node.nodeType==1){var bindings={};var binding=node.firstChild;while(binding!=null){if(binding.nodeType==1&&binding.firstChild!=null&&binding.firstChild.nodeType==1&&binding.firstChild.firstChild!=null&&binding.firstChild.firstChild.nodeType==3){bindings[binding.getAttribute('name')]=binding.firstChild.firstChild.nodeValue;}
binding=binding.nextSibling;}
if(bindings["start"]==null&&bindings["date"]!=null){bindings["start"]=bindings["date"];}
var evt=new Timeline.DefaultEventSource.Event(parseDateTimeFunction(bindings["start"]),parseDateTimeFunction(bindings["end"]),parseDateTimeFunction(bindings["latestStart"]),parseDateTimeFunction(bindings["earliestEnd"]),bindings["isDuration"]!="true",bindings["title"],bindings["description"],this._resolveRelativeURL(bindings["image"],base),this._resolveRelativeURL(bindings["link"],base),this._resolveRelativeURL(bindings["icon"],base),bindings["color"],bindings["textColor"]);evt._bindings=bindings;evt.getProperty=function(name){return this._bindings[name];};evt.setWikiInfo(wikiURL,wikiSection);this._events.add(evt);added=true;}
node=node.nextSibling;}
if(added){this._fire("onAddMany",[]);}};Timeline.DefaultEventSource.prototype.add=function(evt){this._events.add(evt);this._fire("onAddOne",[evt]);};Timeline.DefaultEventSource.prototype.addMany=function(events){for(var i=0;i<events.length;i++){this._events.add(events[i]);}
this._fire("onAddMany",[]);};Timeline.DefaultEventSource.prototype.clear=function(){this._events.removeAll();this._fire("onClear",[]);};Timeline.DefaultEventSource.prototype.getEventIterator=function(startDate,endDate){return this._events.getIterator(startDate,endDate);};Timeline.DefaultEventSource.prototype.getAllEventIterator=function(){return this._events.getAllIterator();};Timeline.DefaultEventSource.prototype.getCount=function(){return this._events.getCount();};Timeline.DefaultEventSource.prototype.getEarliestDate=function(){return this._events.getEarliestDate();};Timeline.DefaultEventSource.prototype.getLatestDate=function(){return this._events.getLatestDate();};Timeline.DefaultEventSource.prototype._fire=function(handlerName,args){for(var i=0;i<this._listeners.length;i++){var listener=this._listeners[i];if(handlerName in listener){try{listener[handlerName].apply(listener,args);}catch(e){Timeline.Debug.exception(e);}}}};Timeline.DefaultEventSource.prototype._getBaseURL=function(url){if(url.indexOf("://")<0){var url2=this._getBaseURL(document.location.href);if(url.substr(0,1)=="/"){url=url2.substr(0,url2.indexOf("/",url2.indexOf("://")+3))+url;}else{url=url2+url;}}
var i=url.lastIndexOf("/");if(i<0){return"";}else{return url.substr(0,i+1);}};Timeline.DefaultEventSource.prototype._resolveRelativeURL=function(url,base){if(url==null||url==""){return url;}else if(url.indexOf("://")>0){return url;}else if(url.substr(0,1)=="/"){return base.substr(0,base.indexOf("/",base.indexOf("://")+3))+url;}else{return base+url;}};Timeline.DefaultEventSource.Event=function(start,end,latestStart,earliestEnd,instant,text,description,image,link,icon,color,textColor){this._id="e"+Math.floor(Math.random()*1000000);this._instant=instant||(end==null);this._start=start;this._end=(end!=null)?end:start;this._latestStart=(latestStart!=null)?latestStart:(instant?this._end:this._start);this._earliestEnd=(earliestEnd!=null)?earliestEnd:(instant?this._start:this._end);this._text=Timeline.HTML.deEntify(text);this._description=Timeline.HTML.deEntify(description);this._image=(image!=null&&image!="")?image:null;this._link=(link!=null&&link!="")?link:null;this._icon=(icon!=null&&icon!="")?icon:null;this._color=(color!=null&&color!="")?color:null;this._textColor=(textColor!=null&&textColor!="")?textColor:null;this._wikiURL=null;this._wikiSection=null;};Timeline.DefaultEventSource.Event.prototype={getID:function(){return this._id;},isInstant:function(){return this._instant;},isImprecise:function(){return this._start!=this._latestStart||this._end!=this._earliestEnd;},getStart:function(){return this._start;},getEnd:function(){return this._end;},getLatestStart:function(){return this._latestStart;},getEarliestEnd:function(){return this._earliestEnd;},getText:function(){return this._text;},getDescription:function(){return this._description;},getImage:function(){return this._image;},getLink:function(){return this._link;},getIcon:function(){return this._icon;},getColor:function(){return this._color;},getTextColor:function(){return this._textColor;},getProperty:function(name){return null;},getWikiURL:function(){return this._wikiURL;},getWikiSection:function(){return this._wikiSection;},setWikiInfo:function(wikiURL,wikiSection){this._wikiURL=wikiURL;this._wikiSection=wikiSection;},fillDescription:function(elmt){elmt.innerHTML=this._description;},fillWikiInfo:function(elmt){if(this._wikiURL!=null&&this._wikiSection!=null){var wikiID=this.getProperty("wikiID");if(wikiID==null||wikiID.length==0){wikiID=this.getText();}
wikiID=wikiID.replace(/\s/g,"_");var url=this._wikiURL+this._wikiSection.replace(/\s/g,"_")+"/"+wikiID;var a=document.createElement("a");a.href=url;a.target="new";a.innerHTML=Timeline.strings[Timeline.Platform.clientLocale].wikiLinkLabel;elmt.appendChild(document.createTextNode("["));elmt.appendChild(a);elmt.appendChild(document.createTextNode("]"));}else{elmt.style.display="none";}},fillTime:function(elmt,labeller){if(this._instant){if(this.isImprecise()){elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start)));elmt.appendChild(elmt.ownerDocument.createElement("br"));elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._end)));}else{elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start)));}}else{if(this.isImprecise()){elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start)+" ~ "+labeller.labelPrecise(this._latestStart)));elmt.appendChild(elmt.ownerDocument.createElement("br"));elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._earliestEnd)+" ~ "+labeller.labelPrecise(this._end)));}else{elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._start)));elmt.appendChild(elmt.ownerDocument.createElement("br"));elmt.appendChild(elmt.ownerDocument.createTextNode(labeller.labelPrecise(this._end)));}}},fillInfoBubble:function(elmt,theme,labeller){var doc=elmt.ownerDocument;var title=this.getText();var link=this.getLink();var image=this.getImage();if(image!=null){var img=doc.createElement("img");img.src=image;theme.event.bubble.imageStyler(img);elmt.appendChild(img);}
var divTitle=doc.createElement("div");var textTitle=doc.createTextNode(title);if(link!=null){var a=doc.createElement("a");a.href=link;a.appendChild(textTitle);divTitle.appendChild(a);}else{divTitle.appendChild(textTitle);}
theme.event.bubble.titleStyler(divTitle);elmt.appendChild(divTitle);var divBody=doc.createElement("div");this.fillDescription(divBody);theme.event.bubble.bodyStyler(divBody);elmt.appendChild(divBody);var divTime=doc.createElement("div");this.fillTime(divTime,labeller);theme.event.bubble.timeStyler(divTime);elmt.appendChild(divTime);var divWiki=doc.createElement("div");this.fillWikiInfo(divWiki);theme.event.bubble.wikiStyler(divWiki);elmt.appendChild(divWiki);}};
/* themes.js */
Timeline.ClassicTheme=new Object();Timeline.ClassicTheme.implementations=[];Timeline.ClassicTheme.create=function(locale){if(locale==null){locale=Timeline.Platform.getDefaultLocale();}
var f=Timeline.ClassicTheme.implementations[locale];if(f==null){f=Timeline.ClassicTheme._Impl;}
return new f();};Timeline.ClassicTheme._Impl=function(){this.firstDayOfWeek=0;this.ether={backgroundColors:["#EEE","#DDD","#CCC","#AAA"],highlightColor:"white",highlightOpacity:50,interval:{line:{show:true,color:"#aaa",opacity:25},weekend:{color:"#FFFFE0",opacity:30},marker:{hAlign:"Bottom",hBottomStyler:function(elmt){elmt.className="timeline-ether-marker-bottom";},hBottomEmphasizedStyler:function(elmt){elmt.className="timeline-ether-marker-bottom-emphasized";},hTopStyler:function(elmt){elmt.className="timeline-ether-marker-top";},hTopEmphasizedStyler:function(elmt){elmt.className="timeline-ether-marker-top-emphasized";},vAlign:"Right",vRightStyler:function(elmt){elmt.className="timeline-ether-marker-right";},vRightEmphasizedStyler:function(elmt){elmt.className="timeline-ether-marker-right-emphasized";},vLeftStyler:function(elmt){elmt.className="timeline-ether-marker-left";},vLeftEmphasizedStyler:function(elmt){elmt.className="timeline-ether-marker-left-emphasized";}}}};this.event={track:{offset:0.5,height:1.5,gap:0.5},instant:{icon:Timeline.urlPrefix+"images/dull-blue-circle.png",lineColor:"#58A0DC",impreciseColor:"#58A0DC",impreciseOpacity:20,showLineForNoText:true},duration:{color:"#58A0DC",opacity:100,impreciseColor:"#58A0DC",impreciseOpacity:20},label:{insideColor:"white",outsideColor:"black",width:200},highlightColors:["#FFFF00","#FFC000","#FF0000","#0000FF"],bubble:{width:250,height:125,titleStyler:function(elmt){elmt.className="timeline-event-bubble-title";},bodyStyler:function(elmt){elmt.className="timeline-event-bubble-body";},imageStyler:function(elmt){elmt.className="timeline-event-bubble-image";},wikiStyler:function(elmt){elmt.className="timeline-event-bubble-wiki";},timeStyler:function(elmt){elmt.className="timeline-event-bubble-time";}}};};
/* units.js */
Timeline.NativeDateUnit=new Object();Timeline.NativeDateUnit.createLabeller=function(locale,timeZone){return new Timeline.GregorianDateLabeller(locale,timeZone);};Timeline.NativeDateUnit.makeDefaultValue=function(){return new Date();};Timeline.NativeDateUnit.cloneValue=function(v){return new Date(v.getTime());};Timeline.NativeDateUnit.getParser=function(format){if(typeof format=="string"){format=format.toLowerCase();}
return(format=="iso8601"||format=="iso 8601")?Timeline.DateTime.parseIso8601DateTime:Timeline.DateTime.parseGregorianDateTime;};Timeline.NativeDateUnit.parseFromObject=function(o){return Timeline.DateTime.parseGregorianDateTime(o);};Timeline.NativeDateUnit.toNumber=function(v){return v.getTime();};Timeline.NativeDateUnit.fromNumber=function(n){return new Date(n);};Timeline.NativeDateUnit.compare=function(v1,v2){var n1,n2;if(typeof v1=="object"){n1=v1.getTime();}else{n1=Number(v1);}
if(typeof v2=="object"){n2=v2.getTime();}else{n2=Number(v2);}
return n1-n2;};Timeline.NativeDateUnit.earlier=function(v1,v2){return Timeline.NativeDateUnit.compare(v1,v2)<0?v1:v2;};Timeline.NativeDateUnit.later=function(v1,v2){return Timeline.NativeDateUnit.compare(v1,v2)>0?v1:v2;};Timeline.NativeDateUnit.change=function(v,n){return new Date(v.getTime()+n);};
Timeline.GregorianDateLabeller.monthNames["en"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
Timeline.strings["en"] = {wikiLinkLabel:"Discuss"};
} // end of 'install only once'
/*}}}*/
/***
From:
// http://simile.mit.edu/repository/timeline/trunk/src/webapp/api/bundle.css
***/
/*{{{*/
.timeline-ether-marker-bottom {
width: 5em;
height: 1.5em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: #aaa;
}
.timeline-ether-marker-bottom-emphasized {
width: 5em;
height: 2em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: black;
}
.timeline-ether-marker-top {
width: 5em;
height: 1.5em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: #aaa;
}
.timeline-ether-marker-top-emphasized {
width: 5em;
height: 2em;
border-left: 1px solid #aaa;
padding-left: 2px;
color: black;
}
.timeline-ether-marker-right {
width: 5em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: #aaa;
}
.timeline-ether-marker-right-emphasized {
width: 7em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: black;
}
.timeline-ether-marker-left {
width: 5em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: #aaa;
}
.timeline-ether-marker-left-emphasized {
width: 7em;
height: 1.5em;
border-top: 1px solid #aaa;
padding-top: 2px;
color: black;
}
.timeline-duration-event {
position: absolute;
overflow: hidden;
border: 1px solid blue;
}
.timeline-instant-event2 {
position: absolute;
overflow: hidden;
border-left: 1px solid blue;
padding-left: 2px;
}
.timeline-instant-event {
position: absolute;
overflow: hidden;
}
.timeline-event-bubble-title {
font-weight: bold;
border-bottom: 1px solid #888;
margin-bottom: 0.5em;
}
.timeline-event-bubble-body {
}
.timeline-event-bubble-wiki {
margin: 0.5em;
text-align: right;
color: #A0A040;
}
.timeline-event-bubble-wiki a {
color: #A0A040;
}
.timeline-event-bubble-time {
color: #aaa;
}
.timeline-event-bubble-image {
float: right;
padding-left: 5px;
padding-bottom: 5px;
}.timeline-container {
position: relative;
overflow: hidden;
}
.timeline-copyright {
position: absolute;
bottom: 0px;
left: 0px;
z-index: 1000;
cursor: pointer;
}
.timeline-message-container {
position: absolute;
top: 30%;
left: 35%;
right: 35%;
z-index: 1000;
display: none;
}
.timeline-message {
font-size: 120%;
font-weight: bold;
text-align: center;
}
.timeline-message img {
vertical-align: middle;
}
.timeline-band {
position: absolute;
background: #eee;
z-index: 10;
}
.timeline-band-inner {
position: relative;
width: 100%;
height: 100%;
}
.timeline-band-input {
position: absolute;
width: 1em;
height: 1em;
overflow: hidden;
z-index: 0;
}
.timeline-band-input input{
width: 0;
}
.timeline-band-layer {
position: absolute;
width: 100%;
height: 100%;
}
.timeline-band-layer-inner {
position: relative;
width: 100%;
height: 100%;
}
/*}}}*/
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.7|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Show tiddlers one at a time with automatic permalink, or always open tiddlers at top/bottom of page.|
This plugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one tiddler displayed at a time.
!!!!!Documentation
>see [[SinglePageModePluginInfo]]
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)
Notes:
* The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}.
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2010.11.30 2.9.7 use story.getTiddler()
2008.10.17 2.9.6 changed chkSinglePageAutoScroll default to false
| Please see [[SinglePageModePluginInfo]] for previous revision details |
2005.08.15 1.0.0 Initial Release. Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts.
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageModePlugin= {major: 2, minor: 9, revision: 7, date: new Date(2010,11,30)};
//}}}
//{{{
config.paramifiers.SPM = { onstart: function(v) {
config.options.chkSinglePageMode=eval(v);
if (config.options.chkSinglePageMode && config.options.chkSinglePagePermalink && !config.browser.isSafari) {
config.lastURL = window.location.hash;
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
} };
//}}}
//{{{
if (config.options.chkSinglePageMode==undefined)
config.options.chkSinglePageMode=false;
if (config.options.chkSinglePagePermalink==undefined)
config.options.chkSinglePagePermalink=true;
if (config.options.chkSinglePageKeepFoldedTiddlers==undefined)
config.options.chkSinglePageKeepFoldedTiddlers=false;
if (config.options.chkSinglePageKeepEditedTiddlers==undefined)
config.options.chkSinglePageKeepEditedTiddlers=false;
if (config.options.chkTopOfPageMode==undefined)
config.options.chkTopOfPageMode=false;
if (config.options.chkBottomOfPageMode==undefined)
config.options.chkBottomOfPageMode=false;
if (config.options.chkSinglePageAutoScroll==undefined)
config.options.chkSinglePageAutoScroll=false;
//}}}
//{{{
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; // no change in hash
var tids=decodeURIComponent(window.location.hash.substr(1)).readBracketedList();
if (tids.length==1) // permalink (single tiddler in URL)
story.displayTiddler(null,tids[0]);
else { // restore permaview or default view
config.lastURL = window.location.hash;
if (!tids.length) tids=store.getTiddlerText("DefaultTiddlers").readBracketedList();
story.closeAllTiddlers();
story.displayTiddlers(null,tids);
}
}
if (Story.prototype.SPM_coreDisplayTiddler==undefined)
Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
{
var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
var tiddlerElem=story.getTiddler(title); // ==null unless tiddler is already displayed
var opt=config.options;
var single=opt.chkSinglePageMode && !startingUp;
var top=opt.chkTopOfPageMode && !startingUp;
var bottom=opt.chkBottomOfPageMode && !startingUp;
if (single) {
story.forEachTiddler(function(tid,elem) {
// skip current tiddler and, optionally, tiddlers that are folded.
if ( tid==title
|| (opt.chkSinglePageKeepFoldedTiddlers && elem.getAttribute("folded")=="true"))
return;
// if a tiddler is being edited, ask before closing
if (elem.getAttribute("dirty")=="true") {
if (opt.chkSinglePageKeepEditedTiddlers) return;
// if tiddler to be displayed is already shown, then leave active tiddler editor as is
// (occurs when switching between view and edit modes)
if (tiddlerElem) return;
// otherwise, ask for permission
var msg="'"+tid+"' is currently being edited.\n\n";
msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
if (!confirm(msg)) return; else story.saveTiddler(tid);
}
story.closeTiddler(tid);
});
}
else if (top)
arguments[0]=null;
else if (bottom)
arguments[0]="bottom";
if (single && opt.chkSinglePagePermalink && !config.browser.isSafari) {
window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
config.lastURL = window.location.hash;
document.title = wikifyPlain("SiteTitle") + " - " + title;
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
if (tiddlerElem && tiddlerElem.getAttribute("dirty")=="true") { // editing... move tiddler without re-rendering
var isTopTiddler=(tiddlerElem.previousSibling==null);
if (!isTopTiddler && (single || top))
tiddlerElem.parentNode.insertBefore(tiddlerElem,tiddlerElem.parentNode.firstChild);
else if (bottom)
tiddlerElem.parentNode.insertBefore(tiddlerElem,null);
else this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
} else
this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
var tiddlerElem=story.getTiddler(title);
if (tiddlerElem&&opt.chkSinglePageAutoScroll) {
// scroll to top of page or top of tiddler
var isTopTiddler=(tiddlerElem.previousSibling==null);
var yPos=isTopTiddler?0:ensureVisible(tiddlerElem);
// if animating, defer scroll until after animation completes
var delay=opt.chkAnimate?config.animDuration+10:0;
setTimeout("window.scrollTo(0,"+yPos+")",delay);
}
}
if (Story.prototype.SPM_coreDisplayTiddlers==undefined)
Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function() {
// suspend single/top/bottom modes when showing multiple tiddlers
var opt=config.options;
var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
this.SPM_coreDisplayTiddlers.apply(this,arguments);
opt.chkBottomOfPageMode=saveBPM;
opt.chkTopOfPageMode=saveTPM;
opt.chkSinglePageMode=saveSPM;
}
//}}}
/***
|Name|SinglePageModePluginInfo|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|Documentation for SinglePageModePlugin|
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. SinglePageModePlugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time.
!!!!!Usage
<<<
When the plugin is enabled, only one tiddler will be displayed at a time and the browser window's titlebar is updated to include the current tiddler title. The browser's location URL is also updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler. Alternatively, even when displaying multiple tiddlers //is// permitted, you can still reduce the potential for confusion by forcing tiddlers to always open at the top (or bottom) of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)
Notes:
* {{block{
The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}. You can also use {{{SPM:expression}}}, where 'expression' is any javascript statement that evaluates to true or false. This allows you to create hard-coded links in other documents that can selectively enable/disable the use of this option based on various programmatic conditions, such as the current username. For example, using
{{{#SPM:config.options.txtUserName!="SomeName"}}}
enables 'one tiddler at a time' display for all users //other than// "~SomeName")}}}
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2008.10.17 2.9.6 changed chkSinglePageAutoScroll default to false
2008.06.12 2.9.5 corrected 'scroll to top of page' logic in auto-scroll handling
2008.06.11 2.9.4 added chkSinglePageKeepEditedTiddlers option
2008.06.05 2.9.3 in displayTiddler(), bypass single/top/bottom mode handling if startingUp. Allows multiple tiddlers to be displayed during startup processing (e.g., #story:DefaultTiddlers), even if single/top/bottom mode is enabled.
2008.04.18 2.9.2 in displayTiddler() and checkLastURL(), handling for Unicode in tiddler titles (remove explicit conversion between Unicode and UTF, as this is apparently done automatically by encode/decodeURIComponent, resulting in double-encoding!
2008.04.08 2.9.1 don't automatically add options to AdvancedOptions shadow tiddler
2008.04.02 2.9.0 in displayTiddler(), when single-page mode is in use and a tiddler is being edited, ask for permission to save-and-close that tiddler, instead of just leaving it open.
2008.03.29 2.8.3 in displayTiddler(), get title from tiddler object (if needed). Fixes errors caused when calling function passes a tiddler *object* instead of a tiddler *title*
2008.03.14 2.8.2 in displayTiddler(), if editing specified tiddler, just move it to top/bottom of story *without* re-rendering (prevents discard of partial edits).
2008.03.06 2.8.1 in paramifier handler, start 'checkURL' timer if chkSinglePageMode is enabled
2008.03.06 2.8.0 added option, {{{config.options.chkSinglePageKeepFoldedTiddlers}}}, so folded tiddlers won't be closed when using single-page mode. Also, in checkURL(), if hash is a ''permaview'' (e.g., "#foo bar baz"), then display multiple tiddlers rather than attempting to display "foo bar baz" as a single tiddler
2008.03.05 2.7.0 added support for "SPM:" URL paramifier
2008.03.01 2.6.0 in hijack of displayTiddler(), added 'title' argument to closeAllTiddlers() so that target tiddler isn't closed-and-reopened if it was already displayed. Also, added config.options.chkSinglePageAutoScrolloption to bypass automatic 'scroll into view' logic (note: core still does it's own ensureVisible() handling)
2007.12.22 2.5.3 in checkLastURL(), use decodeURIComponent() instead of decodeURI so that tiddler titles with commas (and/or other punctuation) are correctly handled.
2007.10.26 2.5.2 documentation cleanup
2007.10.08 2.5.1 in displayTiddler(), when using single-page or top-of-page mode, scrollTo(0,0) to ensure that page header is in view.
2007.09.13 2.5.0 for TPM/BPM modes, don't force tiddler to redisplay if already shown. Allows transition between view/edit or collapsed/view templates, without repositioning displayed tiddler.
2007.09.12 2.4.0 added option to disable automatic permalink feature. Also, Safari is now excluded from permalinking action to avoid bug where tiddlers don't display after hash is updated.
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
<<<
/***
Place your custom CSS here
***/
[[Styles HorizontalMainMenu]]
[[SimileTimelineStyleBundle]]
/*{{{*/
.header {background:#007766;}
#topMenu {background:#007777;}
/*}}}*/
/***
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler.
See http://www.w3schools.com/css/css_colors.asp for a color chart.
***/
/*{{{*/
#mainMenu {position:relative;left:auto;width:auto;text-align:left;line-height:normal;padding 0em 1em 0em 1em;font-size:normal;}
#mainMenu br {display:none;}
#mainMenu {background:#336699;}
#mainMenu {padding:2px;}
#mainMenu .button, #mainMenu .tiddlyLink {padding-left:0.5em;padding-right:0.5em;color:white;font-size:115%;}
/*#displayArea {margin:1em 15.7em 0em 1em;}*/
#displayArea {
/* background-color:#eef;*/
margin-top:0;margin-right:15.5em;margin-bottom:0;margin-left:1em;
padding-top:.1em;padding-bottom:.1em;
}
/*}}}*/
/***
|''Name''|SyntaxHighlighterPlugin3|
|''Description''|Enables syntax highlighting|
|''Author''|PMario|
|''Version''|0.2.1|
|''Status''|''beta''|
|''Source''|http://syntaxhighlighter.tiddlyspace.com/#SyntaxHighlighterPlugin3|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5.0|
|''Requires''|ShCore.js|
|''Keywords''|syntax highlighting color code|
!Documentation
*see: [[SyntaxHighlighterPlugin3Info]]
!Description
Enables syntax highlighting for <pre> and <code> blocks. Adds a new formatter for {{{<code class='brush:???'>}}}
!Usage
!!!!StyleSheet
<<<
*add this to your StyleSheet
{{{
[[ShCore.css]]
[[ShThemeDefault.css]]
}}}
<<<
!!!!Macro
<<<
*The macro is only needed if you have inline html blocks. see: [[SyntaxHighlighterPlugin3Info]]
<<<
!!!!ViewTemplate
<<<
*Same as macro, but will be executed automatically for every tiddler. see: [[SyntaxHighlighterPlugin3Info]]
<<<
!!!!Parameters
<<<
{{{<<highlightSyntax [tagName]>> }}}
*will render all blocks, with any defined tag name. eg: tagName = code.
*[tagName] is optional. Default is "pre".
<<<
!!!!Configuration options
<<<
Guess syntax: <<option chkGuessSyntax>> .. If activated, ~TiddlyWiky <pre> blocks will be rendered according to there block braces. see [[SyntaxHighlighterPlugin3Info]]
Expert mode: <<option chkExpertSyntax>> .. If activated, additional values below will be used. see [[SyntaxHighlighterPlugin3Info]]
{{{ {{{ }}} txtShText: <<option txtShText>> eg: 'brush:text tab-size:4 + options'
{{{ /*{{{* / }}} txtShCss: <<option txtShCss>> eg: 'brush:css + options'
{{{ //{{{ }}} txtShPlugin: <<option txtShPlugin>> 'brush:js + options'
{{{ <!--{{{-->> }}} txtShXml: <<option txtShXml>> 'brush:xml + options'
Additional options can be found at: [[SyntaxHighlighter homepage|http://alexgorbatchev.com/SyntaxHighlighter/manual/configuration/]]
<<<
!!!!Revision History
<<<
*V 0.2.1 2011-08-01
**fix wrong error text
*V 0.2.0 2010-08-22
**New formatter for {{{<code class='brush:???'>}}} is available now
**expert mode uses config options now
<<<
!!!!ToDo
<<<
*
<<<
!!!Code
***/
//{{{
version.extensions.SyntaxHighlighterPlugin3 = {major: 0, minor: 2, revision: 1, date: new Date(2011,8,1)};
(function($) {
if(!window.SyntaxHighlighter) {
throw "Missing dependency: ShCore.js (check brushes too)";
}
config.macros.highlightSyntax = {
getElementsByClass: function (searchClass,node,tag) {
var classElements = [];
if ( node == null ) node = document;
if ( tag == null ) tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(:|\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
// the configured tagName can be temporarily overwritten by the macro.
var tagName = params[0] || SyntaxHighlighter.config.tagName;
var arr = this.getElementsByClass('brush', story.findContainingTiddler(place), tagName);
for (i=0; i<arr.length; i++) {
SyntaxHighlighter.highlight(null, arr[i]);
}
} // handler
};
})(jQuery);
//}}}
/***
!!!!!New formatter for {{{<code class='brush:??'>}}}
***/
//{{{
config.formatters.push({
name: "highlightSyntax",
match: "^<code[\\s]+[^>]+>\\n",
element: "pre",
handler: function(w)
{
this.lookaheadRegExp = /<code[\s]+class.*=.*["'](.*)["'].*>\n((?:^[^\n]*\n)+?)(^<\/code>$\n?)/img;
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var options = lookaheadMatch[1];
var text = lookaheadMatch[2];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
var element = createTiddlyElement(w.output,this.element,null,options,text);
SyntaxHighlighter.highlight(null, element);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
});
//}}}
/***
!!!!!Add class attribute to pre, if defined
***/
//{{{
(function(formatters) { //# set up alias
var helper = {};
helper.enclosedTextHelper = function(w){
var attr;
var co = config.options;
var expert = (co.chkExpertSyntax != undefined)? co.chkExpertSyntax : false;
var guess = (co.chkGuessSyntax != undefined)? co.chkGuessSyntax : true;
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
switch(w.matchText) {
case "{{{\n": // text
attr = (expert) ? (co.txtShText) ? (co.txtShText) : 'brush:text' : 'brush:text' ;
break;
case "/*{{{*/\n": // CSS
attr = (expert) ? (co.txtShCss) ? (co.txtShCss) : 'brush:css' : 'brush:css';
break;
case "//{{{\n": // plugin
attr = (expert) ? (co.txtShPlugin) ? (co.txtShPlugin) : 'brush:js' : 'brush:js';
break;
case "<!--{{{-->\n": //template
attr = (expert) ? (co.txtShXml) ? (co.txtShXml) : 'brush:xml' : 'brush:xml';
break;
}
var element = createTiddlyElement(w.output,this.element,null,attr,text);
if (guess || expert) SyntaxHighlighter.highlight(null, element);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
};
// merge the new helper function into formatterHelpers.
merge(config.formatterHelpers, helper);
})(config.formatters); //# end of alias
//}}}
|''Name''|SyntaxHighlighterPlugin3Info|
|''Description''|Documentation for [[SyntaxHighlighterPlugin3]]|
|''Author''|PMario|
|''Version''|0.2.0|
|''Source''|http://syntaxhighlighter.tiddlyspace.com/#SyntaxHighlighterPlugin3|
|''Documentation''|http://syntaxhighlighter.tiddlyspace.com/#SyntaxHighlighterPlugin3Info|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]], libraries used: see the according files: [[ShCore.js]] |
|''Keywords''|syntax highlighting color code|
!Usage
!!!!StyleSheet
<<<
*add this to your StyleSheet
{{{
[[ShCore.css]]
[[ShThemeDefault.css]]
}}}
<<<
!! Feedback / Support
Feedback is very welcome at [[TiddlyWiki group|http://groups.google.com/group/tiddlywiki]]
!!Examples
!!!!Code sample
<<<
<!--{{{-->
<code class="brush:js highlight:[1,3]">
// comment
var a = b = 0;
a = 17;
</code>
<!--}}}-->
will render like
<code class="brush:js highlight:[1,3]">
// comment
var a = b = 0;
a = 17;
</code>
<<<
!!!!Text
<<<
{{{
{{{
this will be rendered as text!
}}}
}}}
<<<
!!!!CSS
<<<
{{{
/*{{{*/
.cssClass {
display: block; !important;
}
/*}}}*/
}}}
will render like:
/*{{{*/
.cssClass {
display: block; !important;
}
/*}}}*/
<<<
!!!!XML
<<<
{{{
<!--{{{-->
<html>
<div id='myId' class='dp50'>some text </div>
</html>
<!--}}}-->
}}}
will render like:
<!--{{{-->
<html>
<div id='myId' class='dp50'>some text </div>
</html>
<!--}}}-->
<<<
!!!!Plugin
<<<
{{{
//{{{
(function($) {
config.macros.highlightSyntax = {
var a = b = 0;
// your code here!
}
})(jQuery);
//}}}
}}}
will render like:
//{{{
(function($) {
config.macros.highlightSyntax = {
var a = b = 0;
// your code here!
}
})(jQuery);
//}}}
<<<
!!Advanced Options
<<<
Guess syntax: <<option chkGuessSyntax>> .. If activated, ~TiddlyWiky <pre> blocks will be rendered according to there block braces, like described obove.
Expert mode: <<option chkExpertSyntax>> .. If activated, additional values below will be used
{{{ {{{ }}} txtShText: <<option txtShText>> eg: 'brush:text tab-size:4 + options'
{{{ /*{{{*/ }}} txtShCss: <<option txtShCss>> eg: 'brush:css + options'
{{{ //{{{ }}} txtShPlugin: <<option txtShPlugin>> 'brush:js + options'
{{{ <!--{{{-->> }}} txtShXml: <<option txtShXml>> 'brush:xml + options'
If you want to change the default values eg for C++, add the following to a [[zzConfig]] tiddler and tag it "systemConfig"
//{{{
config.options.chkGuessSyntax = true;
config.options.chkExpertSyntax = true;
config.options.txtShPlugin = 'brush:cpp tab-size:4';
//}}}
and use the following backets to cover your code
{{{
//{{{
cpp code comes here.
//}}}
}}}
All possible SyntaxHighlighter options can be found at: [[SyntaxHighlighter homepage|http://alexgorbatchev.com/SyntaxHighlighter/manual/configuration/]]
<<<
!! You need a different brush?
* Go to [[syntaxhighlighter brushes page| http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/]]
* Select your brush
* Copy paste it into a tiddler eg: ShBrushCpp.js
** Tag the new tiddler ''systemConfig''
** Save and reload
* Have a look at Advanced options or use the {{{<code class="brush: ... >}}} tag described above.
!!Needed: list tagged syntax
<<list filter [tag[syntax]]>>
!!!Macro
<<<
*The macro is only needed if you have inline html blocks, like shown below.
<!--{{{-->
<html>
<pre class='brush:pascal tab-size:3'>
// your code
<pre>
</html>
<<highlightSyntax>> .. will render the <pre> blocks shown above.
<!--}}}-->
<<<
!!!!ViewTemplate
<<<
*Same as macro, but will be executed automatically for every tiddler.
<!--{{{-->
<div class='tagging' macro='tagging'></div>
<div macro='highlightSyntax'></div> <!-- insert this line -->
<div class='tagClear'></div>
<!--}}}-->
<<<
!!!!Parameters
<<<
{{{<<highlightSyntax [tagName]>>}}}
*will render all blocks, with any defined tag name. eg: tagName = code.
*[tagName] is optional. Default is "pre".
<<<
!!!Revision History
*V 0.2.0 2010-08-22
**New formatter for {{{<code class='brush:???'>}}} is available now
**expert mode uses config options now
*V 0.1.0 2010-08-17
**initial release
<<tableOfContents "label:all tiddlers" sort:title width:40% size:1>>
// define defaults for cookie-based option values
if (config.options.txtTOCSortBy==undefined) config.options.txtTOCSortBy="modified";
if (config.options.txtTOCListSize==undefined) config.options.txtTOCListSize=19;
if (config.options.chkTOCShow==undefined) config.options.chkTOCShow=true;
if (config.options.chkTOCIncludeHidden==undefined) config.options.chkTOCIncludeHidden=false;
// define macro "tableOfContents" to render controls
config.macros.tableOfContents = { label: "contents" };
config.macros.tableOfContents.cmdMax=8; // index of maximum command item
config.macros.tableOfContents.css = '\
.TOC { padding:0.5em 1em 0.5em 1em; }\
.TOC a { padding:0em 0.25em 0em 0.25em; color:inherit; }\
.TOCList { width: 100%; font-size:8pt; margin:0em; }\
';
config.macros.tableOfContents.html = '\
<div style="text-align:right">\
<span style="float:left">\
<a href="JavaScript:;" id="TOCMenu" style="padding: 0em;"\
onclick="onClickTOCMenu(this)" title="show/hide table of contents">%label%</a>\
</span>\
<a href="JavaScript:;" id="TOCSmaller" style="display:inline"\
onclick="resizeTOC(this)" title="reduce list size">–</a>\
<a href="JavaScript:;" id="TOCLarger"style="display:inline"\
onclick="resizeTOC(this)" title="increase list size">+</a>\
<a href="JavaScript:;" id="TOCMaximize"style="display:inline"\
onclick="resizeTOC(this)" title="maximize/restore list size">=</a>\
</div>\
';
config.macros.tableOfContents.handler = function(place,macroName,params) {
var parsedParams = new Array();
parsedParams['label']=this.label;
parsedParams['inline']=false;
while (params.length>0) {
if (params[0]=="label:none") parsedParams['label']="";
else if (params[0].substr(0,6)=="label:") parsedParams['label']=params[0].substr(6);
if (params[0].substr(0,7)=="prompt:") parsedParams['prompt']=params[0].substr(7);
if (params[0].substr(0,8)=="padding:")parsedParams['padding']=params[0].substr(8);
if (params[0].substr(0,7)=="margin:") parsedParams['margin']=params[0].substr(7);
if (params[0].substr(0,5)=="sort:") parsedParams['sortby']=params[0].substr(5);
if (params[0].substr(0,5)=="date:") parsedParams['date']=params[0].substr(5);
if ((params[0]=="size:auto")||(params[0]=="size:0")) parsedParams['autosize']=true;
else if (params[0] && (params[0].substr(0,5)=="size:")) parsedParams['requestedSize']=params[0].substr(5);
if (params[0].substr(0,6)=="width:") parsedParams['width']=params[0].substr(6);
if (params[0]=="hidelist") parsedParams['hidelist']=true;
if (params[0]=="inline") parsedParams['inline']=true;
if (params[0]=="-title") parsedParams['hide_title']=true;
if (params[0]=="-date") parsedParams['hide_date']=true;
if (params[0]=="-author") parsedParams['hide_author']=true;
if (params[0]=="-creator") parsedParams['hide_creator']=true;
if (params[0]=="-tags") parsedParams['hide_tags']=true;
if (params[0]=="-missing") parsedParams['hide_missing']=true;
if (params[0]=="-orphans") parsedParams['hide_orphans']=true;
if (params[0]=="-shadows") parsedParams['hide_shadows']=true;
params.shift();
}
setStylesheet(config.macros.tableOfContents.css,"tableOfContents");
var newTOC=createTiddlyElement(place,parsedParams['inline']?"span":"div",null,"TOC",null)
if (parsedParams['margin']) { newTOC.style.margin=parsedParams['margin']; }
if (parsedParams['padding']) { newTOC.style.padding=parsedParams['padding']; }
if (parsedParams['label']!="") newTOC.innerHTML=config.macros.tableOfContents.html.replace(/%label%/,parsedParams['label']);
var newTOCList=createTOCList(newTOC,parsedParams)
refreshTOCList(newTOCList);
store.addNotification(null,reloadTOCLists); // reload listbox after every tiddler change
}
// IE needs explicit global scoping for functions/vars called from browser events
window.onChangeTOCList=onChangeTOCList;
window.onClickTOCList=onClickTOCList;
window.onDblClickTOCList=onDblClickTOCList;
window.reloadTOCLists=reloadTOCLists;
window.refreshTOCList=refreshTOCList;
window.onClickTOCMenu=onClickTOCMenu;
window.resizeTOC=resizeTOC;
function createTOCList(place,params) {
var list = createTiddlyElement(place,"select",null,"TOCList",params['prompt'])
list.params=params;
list.onchange=onChangeTOCList;
list.onclick=onClickTOCList;
list.ondblclick=onDblClickTOCList;
list.onkeyup=onKeyUpTOCList;
list.style.display=config.options.chkTOCShow ? "block" : "none" ;
list.sortBy=config.options.txtTOCSortBy;
list.dateFormat="DD MMM YYYY";
list.requestedSize=config.options.txtTOCListSize;
list.expandall=false;
list.cmdMax=config.macros.tableOfContents.cmdMax;
if (params['hide_title']) list.cmdMax--;
if (params['hide_date']) list.cmdMax--;
if (params['hide_author']) list.cmdMax--;
if (params['hide_creator']) list.cmdMax--;
if (params['hide_tags']) list.cmdMax--;
if (params['hide_missing']) list.cmdMax--;
if (params['hide_orphans']) list.cmdMax--;
if (params['hide_shadows']) list.cmdMax--;
if (params['sortby']) { list.sortBy=params['sortby']; list.noSortCookie=true; }
if (params['date']) { list.dateFormat=params['date']; }
if (params['autosize']) { list.autosize=true; list.noSizeCookie=true; }
if (params['requestedSize']){ list.requestedSize=params['requestedSize']; list.noSizeCookie=true; }
if (params['width']) { list.style.width=params['width']; }
if (params['hidelist']) { list.style.display ="none" ; list.noShowCookie=true; }
if (params['expandall']) { list.expandall=true; }
return list;
}
function onChangeTOCList() {
var thisTiddler=this.options[this.selectedIndex].value;
if ((this.size==1)&&(thisTiddler!='')&&(this.selectedIndex>this.cmdMax))
story.displayTiddler(null,thisTiddler,1);
refreshTOCList(this);
return false;
}
function onClickTOCList(e) {
if (!e) var e = window.event;
if (this.size==1) return; // don't toggle display for droplist
if (e.shiftKey) { this.expandall=!this.expandall; refreshTOCList(this);}
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();
return true;
}
function onDblClickTOCList(e) {
if (!e) var e = window.event;
var thisTiddler=this.options[this.selectedIndex].value;
if ((thisTiddler!='')&&(this.selectedIndex>this.cmdMax))
story.displayTiddler(null,thisTiddler,1);
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();
return false;
}
function onKeyUpTOCList(e) {
if (!e) var e = window.event;
if (e.keyCode!=13) return true;
var thisTiddler=this.options[this.selectedIndex].value;
if ((thisTiddler!='')&&(this.selectedIndex>this.cmdMax))
story.displayTiddler(null,thisTiddler,1);
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();
return false;
}
function reloadTOCLists() {
var all=document.all? document.all.tags("select") : document.getElementsByTagName("select");
for (var i=0; i<all.length; i++)
if (all[i].className=="TOCList")
{ all[i].selectedIndex=-1; refreshTOCList(all[i]); }
}
function refreshTOCList(list) {
var selectedIndex = list.selectedIndex;
if (selectedIndex==-1) selectedIndex=0;
var sortBy = list.sortBy;
var showHidden = config.options.chkTOCIncludeHidden && !(config.options.chkHttpReadOnly && readOnly);
if (selectedIndex==0) sortBy=list.sortBy; // "nnn tiddlers" heading - use previous sort order
else if (selectedIndex<=list.cmdMax)sortBy=list.value;
else { if (list.options[list.selectedIndex].value=='') expandTOC(list); return; }
list.sortBy = sortBy; // save current sort order
if (!list.noSortCookie) { config.options.txtTOCSortBy=sortBy; saveOptionCookie("txtTOCSortBy"); }
// get the list of tiddlers
var tiddlers = [];
switch (sortBy) {
case "missing": tiddlers=store.getMissingLinks(); break;
case "tags": tiddlers=store.getTags(); break;
case "orphans": tiddlers=store.getOrphans(); break;
case "shadows": for (var t in config.shadowTiddlers) tiddlers.push(t); tiddlers.sort(); break;
default: tiddlers=store.getTiddlers(sortBy=='creator'?'modifier':sortBy,showHidden?'':'excludeLists'); break;
}
// clear current listbox contents
while (list.length > 0) { list.options[0] = null; }
list.saved=null;
// add heading and control items to list
var i=0;
var theHeading=tiddlers.length+' tiddlers:';
if (sortBy=='missing') theHeading=tiddlers.length+' missing tiddlers:';
if (sortBy=='orphans') theHeading=tiddlers.length+' orphaned tiddlers:';
if (sortBy=='tags') theHeading=tiddlers.length+' tags:';
if (sortBy=='shadows') theHeading=tiddlers.length+' shadow tiddlers:';
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var sel=">";
list.options[i++]=new Option(theHeading,'');
function headerOpt(txt,val) { return new Option(((sortBy==val)?sel:indent)+' ['+txt+']',val); }
if (!list.params['hide_title']) list.options[i++]=headerOpt('by title','title');
if (!list.params['hide_date']) list.options[i++]=headerOpt('by date','modified');
if (!list.params['hide_author']) list.options[i++]=headerOpt('by author','modifier');
if (!list.params['hide_creator']) list.options[i++]=headerOpt('by creator','creator');
if (!list.params['hide_tags']) list.options[i++]=headerOpt('by tags','tags');
if (!list.params['hide_missing']) list.options[i++]=headerOpt('missing','missing');
if (!list.params['hide_orphans']) list.options[i++]=headerOpt('orphans','orphans');
if (!list.params['hide_shadows']) list.options[i++]=headerOpt('shadows','shadows');
// output the tiddler list
switch(sortBy) {
case "title":
for (var t = 0; t < tiddlers.length; t++)
list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title);
break;
case "modified":
case "modifier":
case "creator":
if (sortBy=="modified") tiddlers.reverse(); // show newest first
if (sortBy=="creator") { // sort by custom field with fallback value
tiddlers.sort(function (a,b) {
var v1=a.fields.creator||a.modifier;
var v2=b.fields.creator||b.modifier;
return (v1==v2)?0:(v1>v2?1:-1);
});
}
var lastSection = "";
for (var t = 0; t < tiddlers.length; t++){
var tiddler = tiddlers[t];
var theSection = "";
var m=tiddler.modified;
if (sortBy=="modified") theSection=m.getFullYear()+'.'+(m.getMonth()+1)+'.'+m.getDate();
if (sortBy=="modifier") theSection = tiddler.modifier;
if (sortBy=="creator") theSection=tiddler.fields['creator']||tiddler.modifier;
if (theSection != lastSection) {
lastSection = theSection;
if (sortBy=="modified") theSection = m.formatString(list.dateFormat);
list.options[i++] = new Option('+ '+theSection,"");
}
list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title);
}
expandTOC(list);
break;
case "tags":
// tagged tiddlers, by tag
var tagcount=0;
var lastTag = null;
for (var t = 0; t < tiddlers.length; t++) { // actually a list of tags, not tiddlers...
var theTag = tiddlers[t][0]; var tid=store.getTiddler(theTag);
if (tid && tid.isTagged('excludeLists')) continue; // skip excluded tags
var temp = store.getTaggedTiddlers(theTag);
var tagged=[]; for (var q=0; q<temp.length; q++) // hide excluded tiddlers
if (!temp[q].isTagged('excludeLists')) tagged.push(temp[q]);
if (tagged.length) { tagcount++;
list.options[i++]=new Option('+ '+theTag+" ("+tagged.length+")","");
for(var r=0; r<tagged.length; r++)
list.options[i++]=
new Option(indent+indent+tagged[r].title,tagged[r].title);
}
}
// count untagged tiddlers
var temp = store.getTiddlers("title");
var c=0; for (var r=0; r<temp.length;r++) if (!temp[r].tags.length) c++;
// create 'pseudo-tag' listing untagged tiddlers (if any)
if (c>0) {
list.options[i++] = new Option("+ untagged ("+c+")","");
for (var r=0; r<temp.length;r++) if (!temp[r].tags.length)
list.options[i++] = new
Option(indent+indent+temp[r].title,temp[r].title);
}
list.options[0].text=tagcount+' tags:';
expandTOC(list);
break;
case "missing": case "orphans": case "shadows":
for (var t = 0; t < tiddlers.length; t++)
list.options[i++] = new Option(tiddlers[t],tiddlers[t]);
break;
}
list.selectedIndex=selectedIndex; // select current control item
list.size = (list.autosize)?list.options.length:list.requestedSize;
}
// show/hide branch of TOCList based on current selection
function expandTOC(list) {
var selectedIndex = list.selectedIndex;
if (selectedIndex==-1) selectedIndex=0;
var sortBy = list.sortBy;
// don't collapse/expand list for alpha-sorted "flatlist" TOC contents
// or list control items
if ((sortBy=="title")||(sortBy=="missing")||(sortBy=="orphans")||(sortBy=="shadows")) return;
if ((selectedIndex>0)&&(selectedIndex<=list.cmdMax)) return;
// get current selected text/value and cache the
// complete list. Then clear the current list contents
var theText = list.options[selectedIndex].text;
var theValue = list.options[selectedIndex].value;
if (!list.saved) {
list.saved=new Array();
for (var i=0;i<list.length;i++) list.saved[i]=list.options[i];
}
while (list.length > 0) { list.options[0] = null; }
// put back heading items until item text matches current selected heading
var i=0;
for (var t=0; t<list.saved.length; t++) {
var opt=list.saved[t];
if (list.expandall||(opt.value=='')||(i<=list.cmdMax)) list.options[i++] = opt;
if (opt.text==theText) break;
}
selectedIndex=i-1; // this is the NEW index of the current selected heading
// put back items with value!='' until value==''
for ( t++; t<list.saved.length; t++) {
var opt=list.saved[t];
if (list.expandall||opt.value!='') list.options[i++] = opt;
if (opt.value=='') break;
}
// put back remaining items with value==''
for ( ; t<list.saved.length; t++) {
var opt=list.saved[t];
if (list.expandall||opt.value=='') list.options[i++] = opt;
}
list.selectedIndex = selectedIndex;
list.size = (list.autosize)?list.options.length:list.requestedSize;
}
// these functions process clicks on the 'control links' that are displayed above the listbox
function getTOCListFromButton(which) {
var list = null;
switch (which.id) {
case 'TOCMenu':
var theSiblings = which.parentNode.parentNode.parentNode.childNodes;
var thePlace=which.parentNode.parentNode.parentNode.parentNode.parentNode.id;
break;
case 'TOCSmaller': case 'TOCLarger': case 'TOCMaximize':
var theSiblings = which.parentNode.parentNode.childNodes;
var thePlace=which.parentNode.parentNode.parentNode.parentNode.id;
break;
}
for (var k=0; k<theSiblings.length; k++)
if (theSiblings[k].className=="TOCList") { list=theSiblings[k]; break; }
return list;
}
function onClickTOCMenu(which) {
var list=getTOCListFromButton(which); if (!list) return;
var opening = list.style.display=="none";
if(config.options.chkAnimate) anim.startAnimating(new Slider(list,opening,false,"none"));
else list.style.display = opening ? "block" : "none" ;
if (!list.noShowCookie) { config.options.chkTOCShow = opening; saveOptionCookie("chkTOCShow"); }
return(false);
}
function resizeTOC(which) {
var list=getTOCListFromButton(which); if (!list) return;
var size = list.size;
if (list.style.display=="none") // make sure list is visible
if(config.options.chkAnimate) anim.startAnimating(new Slider(list,true,false,"none"));
else list.style.display = "block" ;
switch (which.id) {
case 'TOCSmaller': // decrease current listbox size
if (list.autosize) { list.autosize=false; size=config.options.txtTOCListSize; }
if (size==1) break;
size -= 1; // shrink by one line
list.requestedSize = list.size = size;
break;
case 'TOCLarger': // increase current listbox size
if (list.autosize) { list.autosize=false; size=config.options.txtTOCListSize; }
if (size>=list.options.length) break;
size += 1; // grow by one line
list.requestedSize = list.size = size;
break;
case 'TOCMaximize': // toggle autosize
list.autosize = (list.size!=list.options.length);
list.size = (list.autosize)?list.options.length:list.requestedSize;
break;
}
if (!list.noSizeCookie && !list.autosize)
{ config.options.txtTOCListSize=size; saveOptionCookie("txtTOCListSize"); }
}
|Name|TableOfContentsPluginInfo|
|Source|http://www.TiddlyTools.com/#TableOfContentsPlugin|
|Documentation|http://www.TiddlyTools.com/#TableOfContentsPluginInfo|
|Version|2.4.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for TableOfContentsPlugin|
When there are many tiddlers in a document, the standard 'tabbed list of tiddlers' in the right-hand sidebar can become very long, occupying a lot of page space and requiring a lot scrolling in order to locate and select a tiddler. This plugin replaces the standard tabs with a listbox/droplist control that uses a very small amount of page space, regardless of the number of tiddlers in the document.
!!!!!Usage
<<<
{{{
<<tableOfContents label:... sort:... date:... size:...
width:... padding:... margin:... prompt:... inline hidelist
-title -date -author -creator -tags -missing -orphans -shadows
}}}
*''label:text'' (default="contents")<br>the text that appears above the listbox.
*''sort:fieldtype''<br>sets the initial display order for items in the listbox. 'fieldtype' is one of: ''title, modified, modifier, creator, tags, missing, orphans,'' or ''shadows''.
*''date:format''<br>format for dates in listbox display, using TiddlyWiki date formatting (e.g. "DDD, MMM DD YYY")
*''size:nnn'' (default=1)<br>the initial number of lines to display in the listbox. If size=1, a droplist is created, otherwise a fixed-size listbox is created. You can use "size:0" or "size:auto" to display a varible-height listbox that automatically adjusts to fit the current list contents without scrolling.
*''width:...'' (default=100%)<br>the width of the listbox/droplist, using CSS units cm, px, em, or %. You can also use a ".TOCList" custom CSS class definition to override the built-in CSS declarations for the listbox.
*''padding:...''<br>sets listbox CSS padding style
*''margin:...''<br>sets listbox CSS margin style
*''prompt:...''<br>sets non-selectable prompt text that is displayed as the first line of the listbox //(note: this feature is not supported by the listbox control on all browsers)//. Let's you include a short text message (such as "select a tiddler"), even when displaying a compact single-line droplist.
*''inline''<br>By default, the listbox is rendered inside a {{{<div>}}} element. This keyword causes the plugin to use a {{{<span>}}} instead, allowing for more flexible 'inline' placement when embedded within other content.
*''hidelist''<br>when present, only the listbox label and size controls will be appear when first displayed. Clicking the label toggles the listbox display.
*''-title, -date, -author, -creator, -tags, -missing, -orphans, -shadows''<br>Omits the indicated list command item and corresponding listbox content.
Select (or double-click) a title from the listbox to open a tiddler, or select a 'command' items to set the order and type of tiddlers that are shown in the list:
*''[by title]''<br>displays all tiddlers in the document in alphanumeric order
*''[by date/author/creator/tags]''<br>displays indented sections, sorted accordingly, with headings (indicated by a '+') that can be expanded, one at a time, to view the list of tiddlers in that section. You can also ''shift-click'' on a section heading expand/collapse all sections at once.
*''[missing]''<br>displays tiddlers that have been referenced within the document but do not yet exist.
*''[orphans]''<br>displays tiddlers that do exist in the document but have not been referenced by a link from anywhere else within the document.
*''[shadows]''<br>displays special default/fallback tiddlers that are used by TiddlyWiki to configure built-in features and add-on macros/extensions.
The ''size of the listbox can be adjusted'' so you can view more (or less) tiddler titles at one time. Select ''[-]'' to reduce the size by one line, ''[+]'' to increase the size by one line, or ''[=]'' to autosize the list to fit the current contents (toggles on/off). //Note: If the listbox is reduced to a single line, it displayed as a droplist instead of a fixed-sized listbox.// You can ''show/hide the entire listbox'' by selecting the "contents" label that appears above the listbox.
<<<
!!!!!Configuration
<<option chkTOCShow>> display table of contents listbox
<<option chkTOCIncludeHidden>> include tiddlers tagged with <<tag excludeLists>> in listbox
listbox shows <<option txtTOCListSize>> lines, sorted by <<option txtTOCSortBy>>
!!!!!Parameters
<<<
<<<
!!!!!Examples
<<<
{{{<<tableOfContents "label:all tiddlers" sort:title width:40% size:1>>}}}
<<tableOfContents "label:all tiddlers" sort:title width:40% size:1>>
{{{<<tableOfContents "label:by date" sort:modified size:1 width:40%>>}}}
<<tableOfContents "label:by date" sort:modified size:1 width:40%>>
{{{<<tableOfContents "label:tagged tiddlers" sort:tags size:1 width:40%>>}}}
<<tableOfContents "label:tagged tiddlers" sort:tags size:1 width:40%>>
{{{<<tableOfContents "label:shadow tiddlers" sort:shadows size:1 width:40%>>}}}
<<tableOfContents "label:shadow tiddlers" sort:shadows size:1 width:40%>>
<<<
!!!!!Revisions
<<<
2008.04.09 2.4.3 restored config.options.chkTOCShow and onClickTOCMenu() handler
2008.04.07 2.4.2 added "Configuration" section and removed config.options.chkTOCShow and onClickTOCMenu() handler
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.25 2.4.1 code cleanup and performance improvements
2007.12.25 2.4.0 renamed 'system' section to 'shadows' (and no longer list plugins, etc. in that section). Also, added 'by creator' sort order (with fallback to 'modifier' if 'creator' custom field is undefined). Thanks to RA for suggestion and code tweaks.
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.03.22 2.3.2 in refreshTOCLists(), when sorting by date, use convertToLocalYYYYMMDDHHMM() instead of formatString() to compare dates for 'section headings' and only use formatString() when actually generating the section heading date display. Improves performance significantly for date sorted listbox, especially in documents with hundreds of tiddlers. Suggestion by AndreasHoefler.
2007.03.21 2.3.1 in refreshTOCLists(), only get list of 'select' elements, instead of scanning through all elements (saves significant time during refresh events. Suggestion by AndreasHoefler.
2006.11.27 2.3.0 added ability to omit sections from listbox via macro params (e.g., "-date -tags", etc.). Based on request from DavidWinfield.
2006.05.21 2.2.7 added onkeyup handling for enter key (=view selected tiddler, equivalent to double-click)
2006.02.14 2.2.6 FF1501 fix: add 'var r' and 'var k' to unintended global variable declarations in refreshTOCList() and getTOCListFromButton(). Thanks for report from AndreasHoefler.
2006.02.04 2.2.5 add 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals
2005.12.21 2.2.2 in onClickTOCList() and onDblClickTOCList(), prevent mouse events from 'bubbling' up to other handlers
2005.10.30 2.2.1 in refreshTOCList(), fixed calculation of "showHidden" to check for 'readOnly' (i.e., "via HTTP") flag. Based on a report from LyallPearce
2005.10.30 2.2.0 hide tiddlers tagged with 'excludeLists' (with option to override, i.e., "include hidden tiddlers")
2005.10.09 2.1.0 combined documentation and code in a single tiddler
added click toggle for expand-all vs. show-one-branch
2005.08.07 2.0.0 major re-write to not use static ID values for listbox controls, so that multiple macro instances can exist without corrupting each other or the DOM. Moved HTML and CSS definitions into plugin code instead of using separate tiddlers. Added macro parameters for label, sort, date, size, width, hidelist and showtabs
2005.08.03 1.0.3 added "showtabs" optional parameter
2005.07.27 1.0.2 core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet(). Added show/hide toggle (click on 'contents' link)
2005.07.23 1.0.1 added parameter checks and corrected addNotification() usage
2005.07.20 1.0.0 Initial Release
<<<
/***
|Name|TiddlerTweakerPlugin|
|Source|http://www.TiddlyTools.com/#TiddlerTweakerPlugin|
|Version|2.4.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|select multiple tiddlers and modify author, created, modified and/or tag values|
~TiddlerTweaker is a 'power tool' for TiddlyWiki authors. Select multiple tiddlers from a listbox and 'bulk modify' the creator, author, created, modified and/or tag values of those tiddlers using a compact set of form fields. The values you enter into the fields simultaneously overwrite the existing values in all tiddlers you have selected.
!!!!!Usage
<<<
{{{<<tiddlerTweaker>>}}}
{{smallform{<<tiddlerTweaker>>}}}
By default, any tags you enter into the TiddlerTweaker will //replace// the existing tags in all the tiddlers you have selected. However, you can also use TiddlerTweaker to quickly filter specified tags from the selected tiddlers, while leaving any other tags assigned to those tiddlers unchanged:
>Any tag preceded by a '+' (plus) or '-' (minus), will be added or removed from the existing tags //instead of replacing the entire tag definition// of each tiddler (e.g., enter '-excludeLists' to remove that tag from all selected tiddlers. When using this syntax, care should be taken to ensure that //every// tag is preceded by '+' or '-', to avoid inadvertently overwriting any other existing tags on the selected tiddlers. (note: the '+' or '-' prefix on each tag value is NOT part of the tag value, and is only used by TiddlerTweaker to control how that tag value is processed)
Important Notes:
* TiddlerTweaker is a 'power user' tool that can make changes to many tiddlers at once. ''You should always have a recent backup of your document (or 'save changes' just *before* tweaking the tiddlers), just in case you accidentally 'shoot yourself in the foot'.''
* The date and author information on any tiddlers you tweak will ONLY be updated if the corresponding checkboxes have been selected. As a general rule, after using TiddlerTweaker, always ''//remember to save your document//'' when you are done, even though the tiddler timeline tab may not show any recently modified tiddlers.
* Selecting and updating all tiddlers in a document can take a while. Your browser may warn about an 'unresponsive script'. Usually, if you allow it to continue, it should complete the processing... eventually. Nonetheless, be sure to save your work before you begin tweaking lots of tiddlers, just in case something does get stuck.
<<<
!!!!!Revisions
<<<
2011.01.21 2.4.5 auto-selection: use "-" for untagged tiddlers. Also, added 'opened', 'invert'
2009.09.15 2.4.4 added 'edit' button. moved html definition to separate section
2009.09.13 2.4.3 in settiddlers(), convert backslashed chars (\n\b\s\t) in replacement text
2009.06.26 2.4.2 only add brackets around tags containing spaces
2009.06.22 2.4.1 in setFields(), add brackets around all tags shown tweaker edit field
2009.03.30 2.4.0 added 'sort by modifier'
2009.01.22 2.3.0 added support for text pattern find/replace
2008.10.27 2.2.3 in setTiddlers(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.09.07 2.2.2 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.05.12 2.2.1 replace built-in backstage tweak task with tiddler tweaker control panel (moved from BackstageTweaks)
2008.01.13 2.2.0 added 'auto-selection' links: all, changed, tags, title, text
2007.12.26 2.1.0 added support for managing 'creator' custom field (see [[CoreTweaks]])
2007.11.01 2.0.3 added config.options.txtTweakerSortBy for cookie-based persistence of list display order preference setting.
2007.09.28 2.0.2 in settiddlers() and deltiddlers(), added suspend/resume notification handling (improves performance when operating on multiple tiddlers)
2007.08.03 2.0.1 added shadow definition for [[TiddlerTweaker]] tiddler for use as parameter references with {{{<<tiddler>>, <<slider>> or <<tabs>>}}} macros.
2007.08.03 2.0.0 converted from inline script
2006.01.01 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TiddlerTweakerPlugin= {major: 2, minor: 4, revision: 5, date: new Date(2011,1,21)};
// shadow tiddler
config.shadowTiddlers.TiddlerTweaker='<<tiddlerTweaker>>';
// defaults
if (config.options.txtTweakerSortBy==undefined) config.options.txtTweakerSortBy='modified';
// backstage task
if (config.tasks) { // for TW2.2b3 or above
config.tasks.tweak.tooltip='review/modify tiddler internals: dates, authors, tags, etc.';
config.tasks.tweak.content='{{smallform small groupbox{<<tiddlerTweaker>>}}}';
}
// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
window.removeCookie=function(name) {
document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
}
}
config.macros.tiddlerTweaker = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var span=createTiddlyElement(place,'span');
span.innerHTML=store.getTiddlerText('TiddlerTweakerPlugin##html');
this.init(span.getElementsByTagName('form')[0],config.options.txtTweakerSortBy);
},
init: function(f,sortby) { // set form controls
if (!f) return; // form might not be rendered yet...
while (f.list.options[0]) f.list.options[0]=null; // empty the list
var tids=store.getTiddlers(sortby);
if (sortby=='size') // descending order
tids.sort(function(a,b) {return a.text.length > b.text.length ? -1 : (a.text.length == b.text.length ? 0 : +1);});
var who='';
for (i=0; i<tids.length; i++) { var t=tids[i];
var label=t.title; var value=t.title;
switch (sortby) {
case 'modified':
case 'created':
var t=tids[tids.length-i-1]; // reverse order
var when=t[sortby].formatString('YY.0MM.0DD 0hh:0mm ');
label=when+t.title;
value=t.title;
break;
case 'size':
label='['+t.text.length+'] '+label;
break;
case 'modifier':
case 'creator':
if (who!=t[sortby]) {
who=t[sortby];
f.list.options[f.list.length]=new Option('by '+who+':','',false,false);
}
label='\xa0\xa0\xa0'+label; // indent
break;
}
f.list.options[f.list.length]=new Option(label,value,false,false);
}
f.title.value=f.who.value=f.creator.value=f.tags.value='';
f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value='';
f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value='';
f.stats.disabled=f.set.disabled=f.del.disabled=f.edit.disabled=f.display.disabled=true;
f.settitle.disabled=false;
config.options.txtTweakerSortBy=sortby;
f.sortby.value=sortby; // sync droplist
if (sortby!='modified') saveOptionCookie('txtTweakerSortBy');
else removeCookie('txtTweakerSortBy');
},
enablefields: function(here) { // enables/disables inputs based on #items selected
var f=here.form; var list=f.list;
var c=0; for (i=0;i<list.length;i++) if (list.options[i].selected) c++;
if (c>1) f.title.disabled=true;
if (c>1) f.settitle.checked=false;
f.set.disabled=(c==0);
f.del.disabled=(c==0);
f.edit.disabled=(c==0);
f.display.disabled=(c==0);
f.settitle.disabled=(c>1);
f.stats.disabled=(c==0);
var msg=(c==0)?'select tiddlers':(c+' tiddler'+(c!=1?'s':'')+' selected');
here.previousSibling.firstChild.firstChild.nextSibling.innerHTML=msg;
if (c) clearMessage(); else displayMessage('no tiddlers selected');
},
setfields: function(here) { // set fields from first selected tiddler
var f=here.form;
if (!here.value.length) {
f.title.value=f.who.value=f.creator.value=f.tags.value='';
f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value='';
f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value='';
return;
}
var tid=store.getTiddler(here.value); if (!tid) return;
f.title.value=tid.title;
f.who.value=tid.modifier;
f.creator.value=tid.fields['creator']||''; // custom field - might not exist
f.tags.value=tid.tags.map(function(t){return String.encodeTiddlyLink(t)}).join(' ');
var c=tid.created; var m=tid.modified;
f.cm.value=c.getMonth()+1;
f.cd.value=c.getDate();
f.cy.value=c.getFullYear();
f.ch.value=c.getHours();
f.cn.value=c.getMinutes();
f.mm.value=m.getMonth()+1;
f.md.value=m.getDate();
f.my.value=m.getFullYear();
f.mh.value=m.getHours();
f.mn.value=m.getMinutes();
},
selecttiddlers: function(here,callback) {
var f=here; while (f&&f.nodeName.toLowerCase()!='form')f=f.parentNode;
for (var t=f.list.options.length-1; t>=0; t--)
f.list.options[t].selected=callback(f.list.options[t]);
config.macros.tiddlerTweaker.enablefields(f.list);
return false;
},
settiddlers: function(here) {
var f=here.form; var list=f.list;
var tids=[];
for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
if (!tids.length) { alert('please select at least one tiddler'); return; }
var cdate=new Date(f.cy.value,f.cm.value-1,f.cd.value,f.ch.value,f.cn.value);
var mdate=new Date(f.my.value,f.mm.value-1,f.md.value,f.mh.value,f.mn.value);
if (tids.length>1 && !confirm('Are you sure you want to update these tiddlers:\n\n'+tids.join(', '))) return;
store.suspendNotifications();
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
var title=!f.settitle.checked?tid.title:f.title.value;
var who=!f.setwho.checked?tid.modifier:f.who.value;
var text=tid.text;
if (f.replacetext.checked) {
var r=f.replacement.value.replace(/\\t/mg,'\t').unescapeLineBreaks();
text=text.replace(new RegExp(f.pattern.value,'mg'),r);
}
var tags=tid.tags;
if (f.settags.checked) {
var intags=f.tags.value.readBracketedList();
var addtags=[]; var deltags=[]; var reptags=[];
for (i=0;i<intags.length;i++) {
if (intags[i].substr(0,1)=='+')
addtags.push(intags[i].substr(1));
else if (intags[i].substr(0,1)=='-')
deltags.push(intags[i].substr(1));
else
reptags.push(intags[i]);
}
if (reptags.length)
tags=reptags;
if (addtags.length)
tags=new Array().concat(tags,addtags);
if (deltags.length)
for (i=0;i<deltags.length;i++)
{ var pos=tags.indexOf(deltags[i]); if (pos!=-1) tags.splice(pos,1); }
}
if (!f.setcdate.checked) cdate=tid.created;
if (!f.setmdate.checked) mdate=tid.modified;
store.saveTiddler(tid.title,title,text,who,mdate,tags,tid.fields);
if (f.setcreator.checked) store.setValue(tid.title,'creator',f.creator.value); // set creator
if (f.setcdate.checked) tid.assign(null,null,null,null,null,cdate); // set create date
}
store.resumeNotifications();
this.init(f,f.sortby.value);
},
displaytiddlers: function(here,edit) {
var f=here.form; var list=f.list;
var tids=[];
for (i=0; i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
if (!tids.length) { alert('please select at least one tiddler'); return; }
story.displayTiddlers(story.findContainingTiddler(f),tids,edit?DEFAULT_EDIT_TEMPLATE:null);
},
deltiddlers: function(here) {
var f=here.form; var list=f.list;
var tids=[];
for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
if (!tids.length) { alert('please select at least one tiddler'); return; }
if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
store.suspendNotifications();
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
if (tid.tags.contains('systemConfig')) {
var msg=tid.title+' is tagged with systemConfig.'
+'\n\nRemoving this tiddler may cause unexpected results. Are you sure?';
if (!confirm(msg)) continue;
}
store.removeTiddler(tid.title);
story.closeTiddler(tid.title);
}
store.resumeNotifications();
this.init(f,f.sortby.value);
},
stats: function(here) {
var f=here.form; var list=f.list; var tids=[]; var out=''; var tot=0;
var target=f.nextSibling;
for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
if (!tids.length) { alert('please select at least one tiddler'); return; }
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
out+='[['+tid.title+']] '+tid.text.length+'\n'; tot+=tid.text.length;
}
var avg=tot/tids.length;
out=tot+' bytes in '+tids.length+' selected tiddlers ('+avg+' bytes/tiddler)\n<<<\n'+out+'<<<\n';
removeChildren(target);
target.innerHTML="<hr><font size=-2><a href='javascript:;' style='float:right' "
+"onclick='this.parentNode.parentNode.style.display=\"none\"'>close</a></font>";
wikify(out,target);
target.style.display='block';
}
};
//}}}
/***
//{{{
!html
<style>
.tiddlerTweaker table,
.tiddlerTweaker table tr,
.tiddlerTweaker table td
{ padding:0;margin:0;border:0;white-space:nowrap; }
</style><form class='tiddlerTweaker'><!--
--><table style="width:100%"><tr valign="top"><!--
--><td style="text-align:center;width:99%;"><!--
--><font size=-2><div style="text-align:left;"><span style="float:right"><!--
--> <a href="javascript:;"
title="select all tiddlers"
onclick="return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
return opt.value.length;
});">all</a><!--
--> <a href="javascript:;"
title="select tiddlers currently displayed in the story column"
onclick="return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
return story.getTiddler(opt.value);
});">opened</a><!--
--> <a href="javascript:;"
title="select tiddlers that are new/changed since the last file save"
onclick="var lastmod=new Date(document.lastModified);
return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
var tid=store.getTiddler(opt.value);
return tid&&tid.modified>lastmod;
});
">changed</a><!--
--> <a href="javascript:;"
title="select tiddlers with at least one matching tag"
onclick="var t=prompt('Enter space-separated tags (match one or more). Use \x22-\x22 to match untagged tiddlers');
if (!t||!t.length) return false;
var tags=t.readBracketedList();
return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
var tid=store.getTiddler(opt.value);
return tid&&tags[0]=='-'?!tid.tags.length:tid.tags.containsAny(tags);
});
">tags</a><!--
--> <a href="javascript:;"
title="select tiddlers whose titles include matching text"
onclick="var t=prompt('Enter a title (or portion of a title) to match');
if (!t||!t.length) return false;
return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
return opt.value.indexOf(t)!=-1;
});
">titles</a><!--
--> <a href="javascript:;"
title="select tiddlers containing matching text"
onclick="var t=prompt('Enter tiddler text (content) to match');
if (!t||!t.length) return false;
return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
var tt=store.getTiddlerText(opt.value,'');
return tt.indexOf(t)!=-1;
});
">text</a><!--
--> <a href="javascript:;"
title="reverse selection of all list items"
onclick="return config.macros.tiddlerTweaker.selecttiddlers(this,function(opt){
return !opt.selected;
});">invert</a><!--
--></span><span>select tiddlers</span><!--
--></div><!--
--></font><select multiple name=list size="11" style="width:99.99%"
title="use click, shift-click and/or ctrl-click to select multiple tiddler titles"
onclick="config.macros.tiddlerTweaker.enablefields(this)"
onchange="config.macros.tiddlerTweaker.setfields(this)"><!--
--></select><br><!--
-->show<input type=text size=1 value="11"
onchange="this.form.list.size=this.value; this.form.list.multiple=(this.value>1);"><!--
-->by<!--
--><select name=sortby size=1
onchange="config.macros.tiddlerTweaker.init(this.form,this.value)"><!--
--><option value="title">title</option><!--
--><option value="size">size</option><!--
--><option value="modified">modified</option><!--
--><option value="created">created</option><!--
--><option value="modifier">modifier</option><!--
--></select><!--
--><input type="button" value="refresh"
onclick="config.macros.tiddlerTweaker.init(this.form,this.form.sortby.value)"<!--
--> <input type="button" name="stats" disabled value="totals..."
onclick="config.macros.tiddlerTweaker.stats(this)"><!--
--></td><td style="width:1%"><!--
--><div style="text-align:left"><font size=-2> modify values</font></div><!--
--><table style="width:100%;"><tr><!--
--><td style="padding:1px"><!--
--><input type=checkbox name=settitle unchecked
title="allow changes to tiddler title (rename tiddler)"
onclick="this.form.title.disabled=!this.checked">title<!--
--></td><td style="padding:1px"><!--
--><input type=text name=title size=35 style="width:98%" disabled><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=setcreator unchecked
title="allow changes to tiddler creator"
onclick="this.form.creator.disabled=!this.checked">created by<!--
--></td><td style="padding:1px;"><!--
--><input type=text name=creator size=35 style="width:98%" disabled><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=setwho unchecked
title="allow changes to tiddler author"
onclick="this.form.who.disabled=!this.checked">modified by<!--
--></td><td style="padding:1px"><!--
--><input type=text name=who size=35 style="width:98%" disabled><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=setcdate unchecked
title="allow changes to created date"
onclick="var f=this.form;
f.cm.disabled=f.cd.disabled=f.cy.disabled=f.ch.disabled=f.cn.disabled=!this.checked"><!--
-->created on<!--
--></td><td style="padding:1px"><!--
--><input type=text name=cm size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> / <input type=text name=cd size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> / <input type=text name=cy size=4 style="width:3em;padding:0;text-align:center" disabled><!--
--> at <input type=text name=ch size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> : <input type=text name=cn size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=setmdate unchecked
title="allow changes to modified date"
onclick="var f=this.form;
f.mm.disabled=f.md.disabled=f.my.disabled=f.mh.disabled=f.mn.disabled=!this.checked"><!--
-->modified on<!--
--></td><td style="padding:1px"><!--
--><input type=text name=mm size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> / <input type=text name=md size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> / <input type=text name=my size=4 style="width:3em;padding:0;text-align:center" disabled><!--
--> at <input type=text name=mh size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--> : <input type=text name=mn size=2 style="width:2em;padding:0;text-align:center" disabled><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=replacetext unchecked
title="find/replace matching text"
onclick="this.form.pattern.disabled=this.form.replacement.disabled=!this.checked">replace text<!--
--></td><td style="padding:1px"><!--
--><input type=text name=pattern size=15 value="" style="width:40%" disabled
title="enter TEXT PATTERN (regular expression)"> with<!--
--><input type=text name=replacement size=15 value="" style="width:40%" disabled
title="enter REPLACEMENT TEXT"><!--
--></td></tr><tr><td style="padding:1px"><!--
--><input type=checkbox name=settags checked
title="allow changes to tiddler tags"
onclick="this.form.tags.disabled=!this.checked">tags<!--
--></td><td style="padding:1px"><!--
--><input type=text name=tags size=35 value="" style="width:98%"
title="enter new tags or use '+tag' and '-tag' to add/remove tags from existing tags"><!--
--></td></tr></table><!--
--><div style="text-align:center"><!--
--><nobr><input type=button name=display disabled style="width:24%" value="display"
title="show selected tiddlers"
onclick="config.macros.tiddlerTweaker.displaytiddlers(this,false)"><!--
--> <input type=button name=edit disabled style="width:23%" value="edit"
title="edit selected tiddlers"
onclick="config.macros.tiddlerTweaker.displaytiddlers(this,true)"><!--
--> <input type=button name=del disabled style="width:24%" value="delete"
title="remove selected tiddlers"
onclick="config.macros.tiddlerTweaker.deltiddlers(this)"><!--
--> <input type=button name=set disabled style="width:24%" value="update"
title="update selected tiddlers"
onclick="config.macros.tiddlerTweaker.settiddlers(this)"></nobr><!--
--></div><!--
--></td></tr></table><!--
--></form><span style="display:none"><!--content replaced by tiddler "stats"--></span>
!end
//}}}
***/
<<SimileTimeline TiddlersTimelineSpec>>
|timelineHeight:|400|
|band0.width:|80%|
|band0.intervalUnit:|MONTH|
|band0.intervalPixels:|100|
|band0.date:|Dec 1 2007|
|band0.eventSourceType:|tiddlerFields|
|band1.width:|5%|
|band1.intervalUnit:|WEEK|
|band1.intervalPixels:|100*7/31|
|band2.width:|15%|
|band2.intervalUnit:|MONTH|
|band2.intervalPixels:|25|
|band2.showEventText:|false|
|band2.eventSourceType:|tiddlerFields|
~TiddlyWiki is a complete [[wiki|WikiWikiWeb]] in a single HTML file. It contains the entire text of the wiki, and all the ~JavaScript, CSS and HTML goodness to be able to display it, and let you edit it or search it - without needing a server. Although, having said that, there are some fine ServerSide adaptations out there.
[[TiddlyWiki|http://www.tiddlywiki.com/]] was originally created by JeremyRuston and is now a thriving [[open source|OpenSourceLicense]] project with a busy [[Community]] of independent developers. [[Osmosoft]], part of [[BT|http://btplc.com]], is the leading contributor to the project.
<<SimileTimeline Example1TimelineSpec>>
<<SimileTimeline Example2TimelineSpec>>
|~ViewToolbar|collapseTiddler collapseOthers RefreshCommand snapshotPrint closeTiddler closeOthers +editTiddler > < * fields permalink references jump|
|~CollapsedToolbar|expandTiddler collapseOthers RefreshCommand snapshotPrint closeTiddler closeOthers +editTiddler > < * fields permalink references jump|
|~EditToolbar|+saveTiddler -cancelTiddler copyTiddler deleteTiddler autosizeEditor|
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'infoboxes';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 29/10/2012 10:49:26 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 29/10/2012 15:12:23 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 05/11/2012 11:09:20 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . | failed |
| 05/11/2012 11:09:35 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 03/04/2013 21:47:32 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 03/04/2013 21:49:28 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 17/04/2013 16:01:20 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 22/04/2013 12:40:10 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
| 22/04/2013 12:57:24 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . | ok |
| 22/04/2013 12:57:52 | Kristjan | [[/|http://infoboxes.tiddlyspot.com/]] | [[store.cgi|http://infoboxes.tiddlyspot.com/store.cgi]] | . | [[index.html | http://infoboxes.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''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|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 3,
date: new Date("Feb 24, 2008"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// 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
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
//See also [[Wiki Link Formatting]]//
|Style|Formatting|h
|''bold''|{{{''bold''}}} - two single-quotes, not a double-quote|
|//italics//|{{{//italics//}}}|
|''//bold italics//''|{{{''//bold italics//''}}}|
|__underline__|{{{__underline__}}}|
|--strikethrough--|{{{--Strikethrough--}}}|
|super^^script^^|{{{super^^script^^}}}|
|sub~~script~~|{{{sub~~script~~}}}|
|@@Highlight@@|{{{@@Highlight@@}}}|
|{{{plain text}}}|{{{ {{{PlainText No ''Formatting''}}} }}}|
|/%this text will be invisible%/hidden text|{{{/%this text will be invisible%/}}}|
Line breaks can be forced explicitly:
{{{
Some text with a<br>line break in the middle
}}}
Displays as:
Some text with a<br>line break in the middle
!Ordered Lists
Lists can be ordered with numbers and letters:
{{{
#List item one
##List item two
###List item three
}}}
Displays as:
#List item one
##List item two
###List item three
!Unordered Lists
Lists can be unordered:
{{{
*Unordered List Level 1
**Unordered List Level 2
***Unordered List Level 3
}}}
Displays as:
*Unordered List Level 1
**Unordered List Level 2
***Unordered List Level 3
!Definition Lists
Definition lists can also be created:
{{{
;Title 1
:Definition of title 1
;Title 2
:Definition of title 2
}}}
Displays as:
;Title 1
:Definition of title 1
;Title 2
:Definition of title 2
!Headings
Let's say that, for some reason, you need to have a single Tiddler with multiple headings. Put the headings on lines by themselves and add an exclamation point (!) at the beginning of the line. If you want a subheading, use two exclamation points, like so:
!Heading1
!!Subheading1
!!!Subsubheading1
Here's the code for the above stack of subheadings:
{{{
!Heading1
!!Subheading1
!!!Subsubheading1
}}}
//See also [[Wiki Formatting]]//
!Wiki Links
Any words or phrases that are CamelCase or compound words - in which the elements are joined without spaces - will result in them becoming links to tiddlers with that name.
For example,
{{{
WikiWord
}}}
Displays as:
WikiWord
To stop this happening the words must be escaped:
{{{
~WikiWord
}}}
Displays as:
~WikiWord
Alternatively, a tiddler can be linked to using square brackets to encompass the whole tiddler title:
{{{
[[tiddler name]]
}}}
!Pretty Links
Optionally, custom text can be added, separated by a pipe character (|)
{{{
[[alternative link text|tiddler name]]
}}}
Displays as:
[[link to our WikiWord tiddler|WikiWord]]
!External Links
Writing the URL in the text results in a link to that external site:
{{{
http://osmosoft.com
}}}
Displays as:
http://osmosoft.com
Similar to pretty links alternative text can be used to link to external sites:
{{{
[[Visit the Osmosoft site|http://osmosoft.com]]
}}}
Displays as:
[[Visit the Osmosoft site|http://osmosoft.com]]
!Links to Other Spaces
Link to a space by preceding it with {{{@}}}:
{{{
@about
}}}
Displays as:
@about
Suppress space linking with {{{~}}}:
{{{
~@about
}}}
~@about
Link to a tiddler within another space:
{{{
TiddlyWiki@glossary
[[TiddlySpace API]]@glossary
[[Information about the HTTP interface|TiddlySpace API]]@glossary
}}}
Displays as:
TiddlyWiki@glossary
[[TiddlySpace API]]@glossary
[[Information about the HTTP interface|TiddlySpace API]]@glossary
!Simple Tables
{{{
|North West|North|North East|
|West|Here|East|
|South West|South|South East|
}}}
Displays as:
|North West|North|North East|
|West|Here|East|
|South West|South|South East|
!Cell Formatting
*Insert a space before cell content to right justify cell
*Insert a space after cell content to left justify cell
*Insert spaces before and after cell content to centre justify cell
*Insert an exclamation mark ({{{!}}}) as the first non-space character of a cell to turn it into a header cell
For example:
{{{
|!First column|!Second column|!Third column|
|left | centre | right|
}}}
Displays as:
|!First column|!Second column|!Third column|
|left | centre | right|
!Table Headers and Footers
* Mark a table row as a header by adding an 'h' to the end
* Mark a table row as a footer by adding an 'f' to the end
For example:
{{{
|North West|North|North East|h
|West|Here|East|
|South West|South|South East|f
}}}
Displays as:
|North West|North|North East|h
|West|Here|East|
|South West|South|South East|f
!Table Caption
A caption can be added above or below a table by adding a special row marked with a 'c':
{{{
|A caption above the table|c
|North West|North|North East|
|West|Here|East|
|South West|South|South East|
}}}
{{{
|North West|North|North East|
|West|Here|East|
|South West|South|South East|
|A caption below the table|c
}}}
Displays as:
|A caption above the table|c
|North West|North|North East|h
|West|Here|East|
|South West|South|South East|f
|North West|North|North East|h
|West|Here|East|
|South West|South|South East|f
|A caption below the table|c
!Mergine Table Cells
A cell can be merged horizontally with the cell to its right by giving it the text {{{>}}}:
{{{
|North West|North|North East|
|>|>|West and Here and East|
|South West|South|South East|
}}}
Displays as:
|North West|North|North East|
|>|>|West and Here and East|
|South West|South|South East|
A cell can be merged vertically with the cell in the row above by giving it the text {{{~}}}:
{{{
|Westerly|North|North East|
|~|Here|East|
|~|South|South East|
}}}
Displays as:
|Westerly|North|North East|
|~|Here|East|
|~|South|South East|
!Table CSS Formatting
A CSS class can be added to an entire table by adding a special row tagged with a 'k':
{{{
|myClass|k
|North West|North|North East|
|West|Here|East|
|South West|South|South East|
}}}
CSS properties can be added to a table cell by preceding the cell content with CSS name/value pairs. There are two alternative forms of syntax:
{{{
|color:red; North West|opacity:0.5;North|North East|
|color(green):West|Here|East|
|South West|South|South East|
}}}
Displays as:
|color:red; North West|opacity:0.5;North|North East|
|color(green):West|Here|East|
|South West|South|South East|
!Alternating Rows
TiddlyWiki automatically assigns the classes {{{oddRow}}} and {{{evenRow}}} to table rows {{{<TR>}}} elements. These can then be styled via the StyleSheet:
{{{
.viewer tr.oddRow { background-color: #fff; }
.viewer tr.evenRow { background-color: #ffc; }
}}}
|background|#ffd070|
|borderColor|#dd6|
|message|Caution is advised|
|iconURL|icons##attention|
|iconWidth|50|
|message|The following article has been disputed. Refer to comments below.|
|iconURL|icons##attention|
|iconWidth|50|
!warning
images/warning.png
!stop
images/stop.png
!questionmark
images/questionmark.png
!attention
images/attention.png
!hand_finger
images/hand_finger.png
!pencil
images/pencil.png
!info
images/info.png
!speechballoon
images/talk_chat.png
/***
|''Name:''|SimileTimelinePlugin|
|''Description:''|Plugin to support Simile Timelines, see http://simile.mit.edu/SimileTimeline/ |
|''Author:''|Martin Budden ( mjbudden [at] gmail [dot] com)|
|''Source:''|http://www.martinswiki.com/#SimileTimelineBundlePlugin |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/plugins/SimileTimelinePlugin.js |
|''Version:''|0.1.6|
|''Date:''|Mar 4, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]] |
|''~CoreVersion:''|2.2|
Note that to use this pluing you also need:
1) to install SimileTimelineBundlePlugin (see http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/plugins/SimileTimelineBundlePlugin.js )
2) to include [[SimileTimelineStyleBundle]] in your StyleSheet tiddler (see http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/styles/SimileTimelineStyleBundle.css.js )
!!Todo
* fix bubble height and width
* etherpainters
* allow multiple painters per timeline
* multiple event sources per band
* multiple clocks
* JSON
* XML
***/
/*{{{*/
// Ensure that the SimileTimelinePlugin is only installed once.
if(!version.extensions.SimileTimelinePlugin) {
version.extensions.SimileTimelinePlugin = {installed:true};
if(version.major < 2 || (version.major == 2 && version.minor < 2))
{alertAndThrow('SimileTimelineBundlePlugin requires TiddlyWiki 2.2 or newer.');}
config.macros.SimileTimeline = {};
config.macros.SimileTimeline.closeTiddler = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,slowly)
{
config.macros.SimileTimeline.closeTiddler.apply(this,arguments);
if(config.macros.SimileTimeline.tickTitle && config.macros.SimileTimeline.tickTitle==title) {
config.macros.SimileTimeline.clearTick();
}
};
// used for date string in bubble
Timeline.urlPrefix = './'; //!! kludge for now
Timeline.GregorianDateLabeller.prototype.labelPrecise = function(date)
{
var dt = Timeline.DateTime.removeTimeZoneOffset(date,this._timeZone);
var template = "mmm DD, YYYY";
return dt.formatString(template);
//return dt.toUTCString();
};
Timeline.GregorianDateLabeller.labelIntervalWeek = function(date)
{
var dt = Timeline.DateTime.removeTimeZoneOffset(date,this._timeZone);
var text = '' + dt.getWeek();
return {text:text,emphasized:false};
};
Timeline.GregorianDateLabeller.labelIntervalFunctions['en'] = function(date,intervalUnit)
{
if(intervalUnit==Timeline.DateTime.WEEK) {
var dt = Timeline.DateTime.removeTimeZoneOffset(date,this._timeZone);
var text = '' + dt.getWeek();
return {text:text,emphasized:false};
} else {
return this.defaultLabelInterval(date,intervalUnit);
}
};
/*
Timeline.DefaultEventSource.Event.prototype.fillInfoBubble = function(elmt,theme,labeller)
{
var doc = elmt.ownerDocument;
var image = this.getImage();
if(image) {
var img = doc.createElement("img");
img.src = image;
theme.event.bubble.imageStyler(img);
elmt.appendChild(img);
}
var divTitle = doc.createElement("div");
var title = this.getText();
var textTitle = doc.createTextNode(title);
var link = this.getLink();
if(link) {
var a = doc.createElement("a");
a.href = link;
a.appendChild(textTitle);
divTitle.appendChild(a);
} else {
divTitle.appendChild(textTitle);
}
theme.event.bubble.titleStyler(divTitle);
elmt.appendChild(divTitle);
var divBody = doc.createElement("div");
this.fillDescription(divBody);
theme.event.bubble.bodyStyler(divBody);
elmt.appendChild(divBody);
var divTime = doc.createElement("div");
this.fillTime(divTime,labeller);
theme.event.bubble.timeStyler(divTime);
elmt.appendChild(divTime);
var divWiki = doc.createElement("div");
this.fillWikiInfo(divWiki);
theme.event.bubble.wikiStyler(divWiki);
elmt.appendChild(divWiki);
};
*/
Timeline.loadTiddlerJSON = function(title,fn)
{
var tiddler = store.fetchTiddler(title);
try {
var uri = '';
var j = eval('(' + tiddler.text + ')');
fn(j,uri);
} catch(ex) {
console.log(ex);
return exceptionText(ex);
}
};
Timeline.loadTiddlers = function(data,fn)
{
fn(data);
};
Timeline.DefaultEventSource.prototype.loadTiddlers = function(data)
{
var include = true;
var tag = data.params;
if(data.type && data.type=='tiddlerFields') {
if(!tag) {
tag = 'excludeLists';
include = false;
}
}
var url = data.url ? data.url : "dummy";
var base = this._getBaseURL(url);
// wikiURL and wikiSection used for the "Discuss" button.
var wikiURL = data.wikiURL;
var wikiSection = data.wikiSection;
var dateTimeFormat = null;
var parseDateTimeFunction = this._events.getUnit().getParser(dateTimeFormat);
var added = false;
var tiddlers = store.reverseLookup('tags',tag,include);
for(var i=0; i<tiddlers.length; i++) {
//var event = config.macros.SimileTimeline.getEvent(tiddlers[i].title);
var event = tiddlers[i].getSimileTimelineEvent(data.type);
var evt = new Timeline.DefaultEventSource.Event(
parseDateTimeFunction(event.start),
parseDateTimeFunction(event.end),
parseDateTimeFunction(event.latestStart),
parseDateTimeFunction(event.earliestEnd),
event.isDuration || false,
event.title,
event.description,
this._resolveRelativeURL(event.image,base),
this._resolveRelativeURL(event.link,''),
this._resolveRelativeURL(event.icon,base),
event.color,
event.textColor);
evt._obj = event;
evt.getProperty = function(name) {
return this._obj[name];
};
evt.setWikiInfo(wikiURL,wikiSection);
this._events.add(evt);
added = true;
}
if (added) {
this._fire('onAddMany',[]);
}
};
/*
Timeline.loadXML = function(url, f) {
var fError = function(statusText, status, xmlhttp) {
alert("Failed to load data xml from " + url + "\n" + statusText);
};
var fDone = function(xmlhttp) {
var xml = xmlhttp.responseXML;
if (!xml.documentElement && xmlhttp.responseStream) {
xml.load(xmlhttp.responseStream);
}
f(xml,url);
};
SimileAjax.XmlHttp.get(url, fError, fDone);
};
*/
Timeline.loadXMLRemote = function(uri,f) {
var callback = function(status,context,responseText,uri,xhr) {
if(status) {
var xml = xhr.responseXML;
if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
if (!xml.documentElement && xhr.responseStream) {
xml.load(xhr.responseStream);
}
try {
f(xml,uri);
} catch(ex) {
console.log(ex);
return exceptionText(ex);
}
} else {
alert("Failed to load data xml from " + uri + "\n" + xhr.statusText);
}
};
loadRemoteFile(uri,callback)
};
/*
Timeline.loadJSON = function(url, f) {
var fError = function(statusText, status, xmlhttp) {
alert("Failed to load json data from " + url + "\n" + statusText);
};
var fDone = function(xmlhttp) {
f(eval('(' + xmlhttp.responseText + ')'), url);
};
SimileAjax.XmlHttp.get(url, fError, fDone);
};
*/
Timeline.loadJSONRemote = function(uri,f) {
var callback = function(status,context,responseText,uri,xhr) {
if(status) {
var json = responseText;
var data = eval('(' + json + ')');
try {
f(data,uri);
} catch(ex) {
console.log(ex);
return exceptionText(ex);
}
} else {
alert("Failed to load data xml from " + uri + "\n" + xhr.statusText);
}
};
loadRemoteFile(uri,callback)
};
Timeline.loadJSONFile = function(filePath,f) {
var json = loadFile(filePath);
try {
var data = eval('(' + json + ')');
f(data, filePath);
} catch(ex) {
console.log(ex);
return exceptionText(ex);
}
};
Tiddler.prototype.getSimileTimelineEvent = function(type,eventFields)
{
var t = this.title;
var f = eventFields ? eventFields : config.macros.SimileTimeline.eventFields;
var ev = {};
if(type && type=='tiddlerFields') {
ev.start = this.modified;
ev.title = t;
ev.description = this.text ? this.text : '';
ev.link = this.fields.link;
if(!ev.link)
ev.link = 'javascript:story.displayTiddler(null,"' + t + '")';
} else {
ev.start = store.getTiddlerSlice(t,f.start);
ev.latestStart = store.getTiddlerSlice(t,f.latestStart);
ev.end = store.getTiddlerSlice(t,f.end);
ev.earliestEnd = store.getTiddlerSlice(t,f.earliestEnd);
ev.isDuration = store.getTiddlerSlice(t,f.isDuration);
ev.title = store.getTiddlerSlice(t,f.title);
ev.description = store.getTiddlerSlice(t,f.description);
if(!ev.description)
ev.description = '';
ev.image = store.getTiddlerSlice(t,f.image);
ev.link = store.getTiddlerSlice(t,f.link);
if(!ev.link)
ev.link = 'javascript:story.displayTiddler(null,"' + t + '")';
ev.icon = store.getTiddlerSlice(t,f.icon);
ev.color = store.getTiddlerSlice(t,f.color);
ev.textColor = store.getTiddlerSlice(t,f.textColor);
}
return ev;
};
// to allow loading from tiddlers with differently named fields
config.macros.SimileTimeline.eventFields = {
start:'start',latestStart:'latestStart',end:'end',earliestEnd:'earliestEnd',
isDuration:'isDuration',title:'title',description:'description',image:'image',link:'link',
icon:'icon',color:'color',textColor:'textColor'
};
config.macros.SimileTimeline.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
this.clearTick();
var spec = params[0];
var eventSource = new Timeline.DefaultEventSource();
var theme = Timeline.ClassicTheme.create();
var bWidth = store.getTiddlerSlice(spec,'bubbleWidth');
if(bWidth)
theme.event.bubble.width = bWidth;
var bHeight = store.getTiddlerSlice(spec,'bubbleHeight');
if(bHeight)
theme.event.bubble.height = bHeight;
var defaultDate = new Date();
var eventSources = [];
var ev = {};
var bandInfos = [];
var i = 0;
var bandParams = config.macros.SimileTimeline.getBandParams(spec,'0',defaultDate);
while(bandParams) {
if(bandParams.ev.type && bandParams.ev.type != 'none') {
bandParams.bp.eventSource = eventSource;
ev = bandParams.ev;
if(bandParams.ev.type != 'timer') {
ev.source = eventSource;
}
if(eventSources.length==0)// !!!for now only deal with one eventSource
eventSources.push(ev);
}
bandParams.theme = theme;
defaultDate = bandParams.bp.date;
bi = bandParams.bp.zones ? Timeline.createHotZoneBandInfo(bandParams.bp) : Timeline.createBandInfo(bandParams.bp);
bandInfos.push(bi);
if(bandParams.ep) {
var ep = bandParams.ep;
try {
bandInfos[i].etherPainter = new Timeline[ep.etherPainter]({startDate:ep.startDate,multiple:ep.multiple,theme:theme});
} catch(ex) {
}
}
if(bandParams.dec) {
var dec = bandParams.dec;
try {
bandInfos[i].decorators = [new Timeline[dec.decorator]({
startDate:dec.startDate,
endDate:dec.endDate,
startLabel:'',//dec.startLabel,
endLabel:'',//dec.endLabel,
color:dec.color,
opacity:dec.opacity,
theme:theme})];
} catch(ex) {
}
}
if(i>0) {
bandInfos[i].syncWith = 0;
bandInfos[i].highlight = bandParams.highlight;
}
i++;
bandParams = config.macros.SimileTimeline.getBandParams(spec,String(i),defaultDate);
}
var timelineElem = createTiddlyElement(place,'div',null,'simileTimeline');// simileTimeline css class
var tHeight = store.getTiddlerSlice(spec,'timelineHeight');
timelineElem.style['height'] = tHeight ? tHeight + 'px' : '150px';
var tBorder = store.getTiddlerSlice(spec,'timelineBorder');
if(tBorder)
timelineElem.style['border'] = tBorder + 'px';
config.macros.SimileTimeline.timeline = Timeline.create(timelineElem,bandInfos);
var data = {};
for(i=0;i<eventSources.length;i++) {
ev = eventSources[i];
if(ev.type=='timer') {
config.macros.SimileTimeline.tickTitle = tiddler.title;//!!! temporary kludge, only support one timer
config.macros.SimileTimeline.timerId = setTimeout('config.macros.SimileTimeline.tick()',1000);
}
data.type = ev.type;
data.params = ev.params;
if(ev.source) {
switch(data.type) {
case 'XML':
Timeline.loadXMLRemote(data.params,function(xml,url) { if(ev.source) ev.source.loadXML(xml,url); });
break;
case 'tiddlerJSON':
Timeline.loadTiddlerJSON(data.params,function(data,url) { if(ev.source) ev.source.loadJSON(data,url); });
break;
case 'JSON':
Timeline.loadJSONRemote(data.params,function(data,url) { if(ev.source) ev.source.loadJSON(data,url); });
break;
default:
if(data.type||data.params) {
Timeline.loadTiddlers(data,function(data,url) { if(ev.source) ev.source.loadTiddlers(data,url); });
}
break;
}
}
}
eventSource.addMany([]);
};
config.macros.SimileTimeline.tick = function()
{
config.macros.SimileTimeline.timeline.getBand(0).setCenterVisibleDate(new Date());
if(config.macros.SimileTimeline.timerId)
config.macros.SimileTimeline.timerId = setTimeout('config.macros.SimileTimeline.tick()',1000);
};
config.macros.SimileTimeline.clearTick = function()
{
if(config.macros.SimileTimeline.timerId)
clearTimeout(config.macros.SimileTimeline.timerId);
config.macros.SimileTimeline.timerId = null;
};
config.macros.SimileTimeline.getBandParams = function(title,n,defaultDate)
{
var t = title;
var pfx = 'band' + String(n) + '.';
var width = store.getTiddlerSlice(t,pfx+'width');
if(!width)
return null;
var bp = {};
bp.width = width;
var intervalUnit = store.getTiddlerSlice(t,pfx+'intervalUnit');
switch(intervalUnit) {
case 'MILLISECOND':
bp.intervalUnit = 0;
break;
case 'SECOND':
bp.intervalUnit = 1;
break;
case 'MINUTE':
bp.intervalUnit = 2;
break;
case 'HOUR':
bp.intervalUnit = 3;
break;
case 'DAY':
bp.intervalUnit = 4;
break;
case 'WEEK':
bp.intervalUnit = 5;
break;
case 'MONTH':
bp.intervalUnit = 6;
break;
case 'YEAR':
bp.intervalUnit = 7;
break;
case 'DECADE':
bp.intervalUnit = 8;
break;
case 'CENTURY':
bp.intervalUnit = 9;
break;
case 'MILLENNIUM':
bp.intervalUnit = 10;
break;
case 'EPOCH':
bp.intervalUnit = -1;
break;
case 'ERA':
bp.intervalUnit = -2;
break;
default:
bp.intervalUnit = 7;
break;
}
var intervalPixels = store.getTiddlerSlice(t,pfx+'intervalPixels');
bp.intervalPixels = eval(intervalPixels);
var date = store.getTiddlerSlice(t,pfx+'date');
bp.date = date ? Timeline.DateTime.parseGregorianDateTime(date) : defaultDate;
var showEventText = store.getTiddlerSlice(t,pfx+'showEventText');
bp.showEventText = showEventText ? eval(showEventText) : true;
var trackHeight = store.getTiddlerSlice(t,pfx+'trackHeight');
if(trackHeight)
bp.trackHeight = eval(trackHeight);
var trackGap = store.getTiddlerSlice(t,pfx+'trackGap');
if(trackGap)
bp.trackGap = eval(trackGap);
var ret = {};
var ev = {};
ev.type = store.getTiddlerSlice(t,pfx+'eventSourceType');
ev.params = store.getTiddlerSlice(t,pfx+'eventSourceParams');
var etherPainter = store.getTiddlerSlice(t,pfx+'etherPainter');
if(etherPainter) {
var ep = {};
ep.etherPainter = etherPainter;
ep.startDate = store.getTiddlerSlice(t,pfx+'etherPainter.startDate');
ep.multiple = store.getTiddlerSlice(t,pfx+'etherPainter.multiple');
ret.ep = ep;
}
var decorator = store.getTiddlerSlice(t,'decorator');
if(decorator) {
var dec = {};
var pdc = pfx + 'decorator0.';
dec.decorator = decorator;
dec.startDate = store.getTiddlerSlice(t,pdc+'startDate');
dec.endDate = store.getTiddlerSlice(t,pdc+'endDate');
dec.startLabel = store.getTiddlerSlice(t,pdc+'startLabel');
dec.endLabel = store.getTiddlerSlice(t,pdc+'endLabel');
dec.color = store.getTiddlerSlice(t,pdc+'color');
dec.opacity = store.getTiddlerSlice(t,pdc+'opacity');
ret.dec = dec;
}
var highlight = store.getTiddlerSlice(t,pfx+'highlight');
ret.highlight = highlight ? eval(highlight) : false;
ret.ev = ev;
ret.bp = bp;
return ret;
};
} // end of 'install only once'
/*}}}*/
|background|#ffd070|
|borderColor|#cc6600|
|headingColor|#666666|
|heading|Stub Entry|
|messageFontStyle|normal|
|messageColor|#134|
|message|This is a stub entry. Please, edit it and add information.|
|iconURL|icons##pencil|
|iconWidth|50|
|background|#ffd|
|borderColor|#dd6|
|headingColor|#0aa|
|messageColor|#134|
|iconURL|icons##hand_finger|
|iconWidth|50|
|background|#fdd|
|borderColor|#f66|
|headingColor|#800|
|heading|Danger, Will Robinson!!!|
|messageFontStyle|normal|
|messageColor|#900|
|message|Please follow these instructions carefully.|
|iconURL|icons##stop|
|iconWidth|40|