Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
<<newTiddler tag:"Assignment" text:"" label:"Add Assignment" template:"AssignmentEditTemplate" fields:{{"parent:"+"'"+tiddler.title+"'"}} >>
<<newTiddler label:"Add Class" tag:"Class" title:"NewClass" template:"ClassEditTemplate">>
<<newTiddler label:"a new one" title:"NewClass" >>
<<newTiddler tag:{{tiddler.title}} tag:"Class" label:"Add Class" template:"ClassEditTemplate" fields:{{"parent:"+"'"+tiddler.title+"'"}}>>
<<newJournal label:"Add Qualification" text:"" title:"0DD0MMYY0hh0mm0ss" tag:"Qualification" template:"QualificationEditTemplate" fields:{{"parent:"+"'"+tiddler.title+"'"}} >>
<<newTiddler tag:"Student" label:"Add Student" text:"" template:"StudentEditTemplate" >>
<<newTiddler
title: "NewTest"
tag:"Test"
label:"Add Test"
text: "/% JUST GIVE TITLE AND CLICK DONE %/"
fields:{{"parent:"+"'"+tiddler.title+"'"}}
>>
<script label="Add Attendance">
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
var month= store.getValue(tid, 'month');
var year= store.getValue(tid, 'year');
var title= month+year+tid;
var text="";
var template="EditTemplate";
var tags=[]; tags.push("Attendance");
fields={
'parent': tid
}
if(store.getTiddler(title)==null){
var tiddlerElem = story.getTiddler(title);
var customFields =String.encodeHashMap(fields);
story.displayTiddler(null, title, 'EditTemplate', false, null, null);
var tiddlerElem = story.getTiddler(title);
story.addCustomFields(tiddlerElem, customFields);
for (var t = 0; t < tags.length; t++) {
story.setTiddlerTag(title, tags[t], 1);
}
story.getTiddlerField(title, "text").value = text.format([""]);
story.focusTiddler(title, 'title');
return false;
}else{
story.displayTiddler(null, store.fetchTiddler(title));
}
</script>
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
</div>
<div class='title' macro='view title'>Attendance: </div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class="viewer">
<span macro='tiddler ShowParent'></span><br>
<span macro='view min'>Minimum Attendance Required:</span>
<span macro='tiddler ViewAttendanceChart'></span>
<span macro='tiddler CustomAttendanceTemplate'></span>
</div>
<!--}}}-->
/***
|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";
//}}}
/% JUST GIVE TITLE AND CLICK DONE %/
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Documentation
>see [[CheckboxPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)". Also, wrap handlers in "function()" so "return" can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
//}}}
//{{{
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
name: "checkbox",
match: "\\[[xX_ ][\\]\\=\\(\\{]",
lookahead: "\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
// get params
var checked=(lookaheadMatch[1].toUpperCase()=="X");
var id=lookaheadMatch[2];
var target=lookaheadMatch[3];
if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
var fn_init=lookaheadMatch[4];
var fn_clickBefore=lookaheadMatch[5];
var fn_clickAfter=lookaheadMatch[6];
var tid=story.findContainingTiddler(w.output); if (tid) tid=tid.getAttribute("tiddler");
var srctid=w.tiddler?w.tiddler.title:null;
config.macros.checkbox.create(w.output,tid,srctid,w.matchStart+1,checked,id,target,config.checkbox.refresh,fn_init,fn_clickBefore,fn_clickAfter);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} );
config.macros.checkbox = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
if(!(tiddler instanceof Tiddler)) { // if no tiddler passed in try to find one
var here=story.findContainingTiddler(place);
if (here) tiddler=store.getTiddler(here.getAttribute("tiddler"))
}
var srcpos=0; // "inline X" not applicable to macro syntax
var target=params.shift(); if (!target) target="";
var defaultState=params[0]=="checked"; if (defaultState) params.shift();
var id=params.shift(); if (id && !id.length) id=null;
var fn_init=params.shift(); if (fn_init && !fn_init.length) fn_init=null;
var fn_clickBefore=params.shift();
if (fn_clickBefore && !fn_clickBefore.length) fn_clickBefore=null;
var fn_clickAfter=params.shift();
if (fn_clickAfter && !fn_clickAfter.length) fn_clickAfter=null;
var refresh={ tagged:true, tagging:true, container:false };
this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter);
},
create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
// create checkbox element
var c = document.createElement("input");
c.setAttribute("type","checkbox");
c.onclick=this.onClickCheckbox;
c.srctid=srctid; // remember source tiddler
c.srcpos=srcpos; // remember location of "X"
c.container=tid; // containing tiddler (may be null if not in a tiddler)
c.tiddler=tid; // default target tiddler
c.refresh = {};
c.refresh.container = refresh.container;
c.refresh.tagged = refresh.tagged;
c.refresh.tagging = refresh.tagging;
place.appendChild(c);
// set default state
c.checked=defaultState;
// track state in config.options.ID
if (id) {
c.id=id.substr(1); // trim off leading "="
if (config.options[c.id]!=undefined)
c.checked=config.options[c.id];
else
config.options[c.id]=c.checked;
}
// track state in (tiddlername|tagname) or (fieldname@tiddlername)
if (target) {
var pos=target.indexOf("@");
if (pos!=-1) {
c.field=pos?target.substr(0,pos):"checked"; // get fieldname (or use default "checked")
c.tiddler=target.substr(pos+1); // get specified tiddler name (if any)
if (!c.tiddler || !c.tiddler.length) c.tiddler=tid; // if tiddler not specified, default == container
if (store.getValue(c.tiddler,c.field)!=undefined)
c.checked=(store.getValue(c.tiddler,c.field)=="true"); // set checkbox from saved state
} else {
var pos=target.indexOf("|"); if (pos==-1) var pos=target.indexOf(":");
c.tag=target;
if (pos==0) c.tag=target.substr(1); // trim leading "|" or ":"
if (pos>0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
if (!c.tag.length) c.tag="checked";
var t=store.getTiddler(c.tiddler);
if (t && t.tags)
c.checked=t.isTagged(c.tag); // set checkbox from saved state
}
}
// trim off surrounding { and } delimiters from init/click handlers
if (fn_init) c.fn_init="(function(){"+fn_init.trim().substr(1,fn_init.length-2)+"})()";
if (fn_clickBefore) c.fn_clickBefore="(function(){"+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+"})()";
if (fn_clickAfter) c.fn_clickAfter="(function(){"+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+"})()";
c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
},
onClickCheckbox: function(event) {
window.place=this;
if (this.init && this.fn_init) // custom function hook to set initial state (run only once)
{ try { eval(this.fn_init); } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
if (!this.init && this.fn_clickBefore) // custom function hook to override changes in checkbox state
{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage("Checkbox onClickBefore error: "+e.toString()); } }
if (this.id)
// save state in config AND cookie (only when ID starts with 'chk')
{ config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }
if (this.srctid && this.srcpos>0 && (!this.id || this.id.substr(0,3)!="chk") && !this.tag && !this.field) {
// save state in tiddler content only if not using cookie, tag or field tracking
var t=store.getTiddler(this.srctid); // put X in original source tiddler (if any)
if (t && this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed
t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);
if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
store.setDirty(true);
}
}
if (this.field) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
// set the field value in the target tiddler
store.setValue(this.tiddler,this.field,this.checked?"true":"false");
// DEBUG: displayMessage(this.field+"@"+this.tiddler+" is "+this.checked);
}
if (this.tag) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
var t=store.getTiddler(this.tiddler);
if (t) {
var tagged=(t.tags && t.tags.indexOf(this.tag)!=-1);
if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
if (!this.checked && tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
}
// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
if (this.checked!=tagged) {
if (this.refresh.tagged) {
if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
story.refreshTiddler(this.tiddler,null,true);
else // the TAGGED tiddler in edit mode (with tags field)
config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked);
}
if (this.refresh.tagging)
if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
}
}
if (!this.init && this.fn_clickAfter) // custom function hook to react to changes in checkbox state
{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage("Checkbox onClickAfter error: "+e.toString()); } }
// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
if (!this.init && this.refresh.container && this.container!=this.tiddler)
if (!story.isDirty(this.container)) story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox
return true;
},
refreshEditorTagField: function(title,tag,set) {
var tagfield=story.getTiddlerField(title,"tags");
if (!tagfield||tagfield.getAttribute("edit")!="tags") return; // if no tags field in editor (i.e., custom template)
var tags=tagfield.value.readBracketedList();
if (tags.contains(tag)==set) return; // if no change needed
if (set) tags.push(tag); // add tag
else tags.splice(tags.indexOf(tag),1); // remove tag
for (var t=0;t<tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
tagfield.value=tags.join(" "); // reassemble tag string (with brackets as needed)
return;
}
}
//}}}
|Name|CheckboxPluginInfo|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|documentation for CheckboxPlugin|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* setting/removing tags on specified tiddlers,
* or, setting custom field values on specified tiddlers,
* or, saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler source content (deprecated).
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Inline (wiki syntax) Usage
<<<
//{{{
[ ]or[_] and [x]or[X]
//}}}
Simple checkboxes using 'Inline X' storage. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets.
>//''NOTE: 'Inline X' syntax has been deprecated...'' This storage format only works properly for checkboxes that are directly embedded and accessed from content in a single tiddler. However, if that tiddler is 'transcluded' into another (by using the {{{<<tiddler TiddlerName>>}}} macro), the 'Inline X' will be ''erroneously stored in the containing tiddler's source content, resulting in corrupted content in that tiddler.'' For anything but the most simple of "to do list" uses, you should select from the various alternative storage methods described below...//
//{{{
[x=id]
//}}}
Assign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.
//{{{
[x(title|tag)] or [x(title:tag)]
//}}}
Initializes and tracks the current checkbox state by setting or removing a particular tag value from a specified tiddler. If you omit the tiddler title (and the | or : separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title|)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to the "inline X" value. If this value is //checked//, or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the tag to it. //''NOTE: beginning with version 2.1.2 of this plugin, the "|" separator is the preferred separator between the title and tag name, as it avoids syntactic ambiguity when ":" is used within tiddler titles or tag names.''//
//{{{
[x(field@tiddler)]
//}}}
Initializes and tracks the current checkbox state by setting a particular custom field value from a specified tiddler. If you omit the tiddler title (but not the "@" separator), the specified field on the current tiddler is used. If you omit the field name, as in {{{(@tiddler)}}}, a default fieldname of {{{checked}}} is assumed. Omitting both the field and the tiddler title, {{{(@)}}}, defaults to setting the "checked" field on the current tiddler. When field tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If the tiddler title named in the parameter does not exist, the checkbox state defaults to the "inline X" value. If this value is //checked// or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the field to it.
//{{{
[x{javascript}{javascript}{javascript}]
//}}}
You can define optional javascript code segments to add custom initialization and/or 'onClick' handlers to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to a globally-defined context object, "place" (which can also be referenced as "window.place").
The first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, but //before the regular checkbox processing in performed// ("onClickBefore"), so that you can apply programmed responses or intercept and override the checkbox state based on custom logic. The third code segment (if present) is executed whenver the checkbox is clicked, //after the regular checkbox processing has completed// ("onClickAfter"), so that you can include "side-effect" processing based on the checkbox state just applied.
>Note: if you want to use the default checkbox initialization processing with a custom onClickBefore/After function, use this syntax:
>{{{[x(tag){}{javascript}]}}} or {{{[x(tag){}{}{javascript}]}}}
<<<
!!!!!Macro usage
<<<
In addition to embedded checkboxes using the wiki syntax described above, a ''macro-based syntax'' is also provided, for use in templates where wiki syntax cannot be directly used. This macro syntax can also be used in tiddler content, as an alternative to the wiki syntax. When embedded in [[PageTemplate]], [[ViewTemplate]], or [[EditTemplate]] (or custom alternative templates), use the following macro syntax:
//{{{
<span macro="checkbox target checked id onInit onClickBefore onClickAfter"></span>
//}}}
or, when embedded in tiddler content, use the following macro syntax:
//{{{
<<checkbox target checked id onInit onClickBefore onClickAfter>>
//}}}
where:
''target''
>is either a tag reference (e.g., ''tagname|tiddlername'') or a field reference (e.g. ''fieldname@tiddlername''), as described above.
''checked'' (optional)
>is a keyword that sets the initial state of the checkbox to "checked". When omitted, the default checkbox state is "unchecked".
''id'' (optional)
>specifies an internal config.options.* ID, as described above. If the ID begins with "chk", a cookie-based persistent value will be created to track the checkbox state in between sessions.
''onInit'' (optional)
>contains a javascript event handler to be performed when the checkbox is initially rendered (see details above).
''onClickBefore'' and/or ''onClickAfter'' (optional)
>contains a javascript event handler to be performed each time the checkbox is clicked (see details above). //note: to use the default onInit handler with a custom onClickBefore/After handler, use "" (empty quotes) or {} (empty function) as a placeholder for the onInit and/or onClickBefore parameters//
<<<
!!!!!Examples
<<<
''checked and unchecked static default ("inline X") values:''
//{{{
[X] label
[_] label
//}}}
>[X] label
>[_] label
''document-based value (id='demo', no cookie):''
//{{{
[_=demo] label
//}}}
>[_=demo] label
''cookie-based value (id='chkDemo'):''
//{{{
[_=chkDemo] label
//}}}
>[_=chkDemo] label
''tag-based value (TogglyTagging):''
//{{{
[_(CheckboxPluginInfo|demotag)]
[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}]
//}}}
>[_(CheckboxPluginInfo|demotag)] toggle 'demotag' (and refresh tiddler display)
>[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}] toggle 'demotag' (no refresh)
''field-based values:''
//{{{
[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
[_(demofield@)] demofield@ (equivalent to demonfield@ current tiddler)
[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
[_(@)] @ (equivalent to checked@ current tiddler)
//}}}
>[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
>[_(demofield@)] demofield@ (current tiddler)
>[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
>[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
>[_(@)] toggle field: @ (defaults to "checked@here")
>click to view current: <<toolbar fields>>
''custom init and onClick functions:''
//{{{
[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
//}}}
>[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
''retrieving option values:''
>config.options['demo']=<script>return config.options['demo']?"true":"false";</script>
>config.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>
<<<
!!!!!Configuration
<<<
Normally, when a checkbox state is changed, the affected tiddlers are automatically re-rendered, so that any checkbox-dependent dynamic content can be updated. There are three possible tiddlers to be re-rendered, depending upon where the checkbox is placed, and what kind of storage method it is using.
*''container'': the tiddler in which the checkbox is displayed. (e.g., this tiddler)
*''tagged'': the tiddler that is being tagged (e.g., "~MyTask" when tagging "~MyTask:done")
*''tagging'': the "tag tiddler" (e.g., "~done" when tagging "~MyTask:done")
You can set the default refresh handling for all checkboxes in your document by using the following javascript syntax either in a systemConfig plugin, or as an inline script. (Substitute true/false values as desired):
{{{config.checkbox.refresh = { tagged:true, tagging:true, container:true };}}}
You can also override these defaults for any given checkbox by using an initialization function to set one or more of the refresh options. For example:
{{{[_{place.refresh.container=false}]}}}
<<<
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)". Also, wrap handlers in "function()" so "return" can be used within handler code.
2008.01.02 [2.3.0] split optional custom onClick handling into separate onClickBefore and onClickAfter handlers. The onClickBefore handler permits interception of the click BEFORE the checkbox is set. onClickAfter allows follow-on 'side-effect' processing to occur AFTER the checkbox is set.
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.08.06 [2.2.5] supress automatic refresh of any tiddler that is currently being edited. Ensures that current tiddler edit sessions are not prematurely discarded (losing any changes). However, if checkbox changes a tag on a tiddler being edited, update the "tags" input field (if any) so that saving the edited tiddler correctly reflects any changes due to checkbox activity... see refreshEditorTagField().
2007.07.13 - 2.2.4 in handler(), fix srctid reference (was "w.tiddler", should have been "w.tiddler.title"). This fixes broken 'inline X' plus fatal macro error when using PartTiddlerPlugin. Thanks to cmari for reporting the problem and UdoBorkowski for finding the code error.
2007.06.21 - 2.2.3 suppress automatic refresh of tiddler when using macro-syntax to prevent premature end of tiddler editing session.
2007.06.20 - 2.2.2 fixed handling for 'inline X' when checkboxes are contained in a 'trancluded' tiddler. Now, regardless of where an inline X checkbox appears, the X will be placed in the originating source tiddler, rather than the tiddler in which the checkbox appears.
2007.06.17 - 2.2.1 Refactored code to add checkbox //macro// syntax for use in templates (e.g., {{{macro="checkbox ..."}}}. Also, code cleanup of existing tag handling.
2007.06.16 - 2.2.0 added support for tracking checkbox states using tiddler fields via "(fieldname@tiddlername)" syntax.
2006.05.04 - 2.1.3 fix use of findContainingTiddler() to check for a non-null return value, so that checkboxes won't crash when used outside of tiddler display context (such as in header, sidebar or mainmenu)
2006.03.11 - 2.1.2 added "|" as delimiter to tag-based storage syntax (e.g. "tiddler|tag") to avoid parsing ambiguity when tiddler titles or tag names contain ":". Using ":" as a delimiter is still supported but is deprecated in favor of the new "|" usage. Based on a problem reported by JeffMason.
2006.02.25 - 2.1.0 added configuration options to enable/disable forced refresh of tiddlers when toggling tags
2006.02.23 - 2.0.4 when toggling tags, force refresh of the tiddler containing the checkbox.
2006.02.23 - 2.0.3 when toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.
2006.02.23 - 2.0.2 when using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:
{{{[x([[Tiddler with spaces]]:[[tag with spaces]])]}}}
2006.01.10 - 2.0.1 when toggling tags, force refresh of the 'tagging tiddler'. For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.
2006.01.04 - 2.0.0 update for ~TW2.0
2005.12.27 - 1.1.2 Fix lookAhead regExp handling for {{{[x=id]}}}, which had been including the "]" in the extracted ID.
Added check for "chk" prefix on ID before calling saveOptionCookie()
2005.12.26 - 1.1.2 Corrected use of toUpperCase() in tiddler re-write code when comparing {{{[X]}}} in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.
2005.12.26 - 1.1.0 Revise syntax so all optional parameters are included INSIDE the [ and ] brackets. Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin. Based on a suggestion by GeoffSlocock
2005.12.25 - 1.0.0 added support for tracking checkbox state using tags ("TogglyTagging")
Revised version number for official post-beta release.
2005.12.08 - 0.9.3 support separate 'init' and 'onclick' function definitions.
2005.12.08 - 0.9.2 clean up lookahead pattern
2005.12.07 - 0.9.1 only update tiddler source content if checkbox state is actually different. Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)
2005.12.07 - 0.9.0 initial BETA release
<<<
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<div class="toolbar border" macro="toolbar [[ToolbarCommands::EditRecordToolbar]]"></div>
<h1>Class</h1>
<div class="viewer" >
<table class='editRecord'>
<tr><td>Name:</td><td><span macro='edit title'></span></td></tr>
<tr><td>Teacher:</td><td><span macro='edit teacher'></span></td></tr>
<tr><td>Started on:</td><td><span macro='select date rows:1 *DatesList'></span>-<span macro='select month rows:1 *MonthsList'></span>-<span macro='select year rows:1 *YearsList'></span></td></tr>
<tr><td>Syllabus:</td><td><span macro="edit syllabus 10"></span></td></tr>
<tr><td>Remarks:</td><td><span macro="edit remarks 10"></span></td></tr>
</table>
<span style="display:none" macro="edit tags"></span>
</div>
<!--}}}-->
<html>
<style>
.tiddler{
margin-bottom: 10px;
border: 1px solid #c3c3c3;
}
.tiddler:hover{
background-color: #f8f8f8;
}
.viewer table.record{
border: none;
}
.viewer table.record tr{
border: none;
}
.viewer table.record tr td{
border: 0 solid #ffffff;
padding-top: 5px;
background-color: blue;
}
.viewer table.editRecord tr td input.AttendanceInput{
width: 1em;
}
.alignL{
text-align: left;
}
.alignR{
text-align: right;
}
.tText{
font-weight: bold;
}
</style>
</html>
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
</div>
<div class='title' macro='view title'>Class Id: </div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagged' macro='tags'></div>
<div class="viewer">
<table class='viewRecord'>
<tr><td>Teacher:</td><td><span macro="view teacher"></span></td></tr>
<tr><td>Started on:</td><td><span macro='view date'></span>-<span macro='view month'></span>-<span macro='view year'></span></td></tr>
<tr><td>Syllabus:</td><td><span macro="view syllabus"></span></td></tr>
<tr><td>Remarks:</td><td><span macro="view remarks"></span></td></tr>
</table>
<h2>Enrolled Students:</h2>
<div macro='tiddler ShowStudentList'></div>
<span macro='tiddler ShowStudentsTabs'></span>
<h2>Attendance records:</h2>
<span macro='select month rows:1 "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"'></span>
<span macro='select year rows:1 *YearsList'></span>
<span macro='tiddler AddAttendance'></span>
<span macro='tiddler ListClassAttendance'></span>
<h2>Tests held:</h2>
<span macro='tiddler "Add Test"'></span>
<span macro='tiddler ListClassTests'></span>
<h2>Assignments given:</h2>
<span macro='tiddler "Add Assignment"'></span>
</div>
<div class='tagClear'></div>
<!--}}}-->
/***
|Name|ColumnCalculatorPlugin|
|Source|http://www.TiddlyTools.com/#ColumnCalculatorPlugin|
|Version|0.6.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|calculate values from table cells in a column|
|Status| ALPHA - USE AT YOUR OWN RISK |
!!!Usage
<<<
{{{<<columncalc function startrow endrow>>}}}
where:
*''function'' is a keyword that specifies the type of calculation to perform:
** ''total'' or ''sum'' or //no param//<br>adds up values for cells above it in the column
** ''count''<br>number of non-empty cells in column
** ''average'' or ''avg''<br>average of cells in column (i.e., total/count)
* ''all'' (optional)<br>normally, only cells containing numbers or timestamps (hh:mm:ss) are included in the calculations. The ''all'' keyword allows text or empty cells to be processed as if they contained a "0".
* ''startrow'',''endrow'' (optional)<br>specifies a ONE-based range of rows for limiting the calculation. Use negative numbers to specify an offset from the current row (e.g., {{{<<calc sum 3 5>>}}} adds up rows 3, 4 and 5, while {{{<<calc sum 1 -1>>}}} adds up all numbers in the column excluding the current row (i.e., the same as the default if no startrow/endrow params are specified)
<<<
!!!Examples
<<<
''with numeric values...''
{{{
| foo| 3.2 |
| bar| 1.1 |
| baz| 2.9 |
| gronk| 4.3 |
| snork| non-number |
| count| <<columncalc count all 1 -1>> |
| total| <<columncalc sum all 1 -2>> |
| avg| <<columncalc average all 1 -3>> |
}}}
| foo| 3.2 |
| bar| 1.1 |
| baz| 2.9 |
| gronk| 4.3 |
| snork| non-number |
| count| <<columncalc count all 1 -1>> |
| total| <<columncalc sum all 1 -2>> |
| avg| <<columncalc average all 1 -3>> |
''with time-formatted values (hh:mm:ss)...''
{{{
| foo| 00:22:15 |
| bar| 00:03:30 |
| baz| 00:01:45 |
| count| <<columncalc count 1 -1>> |
| total| <<columncalc sum 1 -2>> |
| avg| <<columncalc average 1 -3>> |
}}}
| foo| 00:22:15 |
| bar| 00:03:30 |
| baz| 00:01:45 |
| count| <<columncalc count 1 -1>> |
| total| <<columncalc sum 1 -2>> |
| avg| <<columncalc average 1 -3>> |
<<<
!!!Revisions
<<<
2009.02.05 [0.6.2] added 'all' param to include empty/text rows in calculations.
2007.10.26 [0.6.1] in handler(), using '.textContent' instead of '.innerHTML' when reading values from table cells. This allows use of values that are transcluded from slices in other tiddlers using the {{{<<tiddler 'TiddlerName::slicename'>>}}} syntax.
2007.06.29 [0.6.0] added support for handling values in hh:mm:ss format
2007.04.02 [0.5.0] started
<<<
!!!!!Code
***/
//{{{
version.extensions.ColumnCalculatorPlugin= {major: 0, minor: 6, revision: 1, date: new Date(2007,10,26)};
config.macros.columncalc= {
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
if (place.parentNode.nodeName.toLowerCase()!='tr') return false; // not in a table
var tbody=place.parentNode.parentNode;
var row=tbody.childNodes.length-1; // current row #
var col=place.parentNode.childNodes.length-1; // current column #
var fn=params.shift();
var allCells=(params[0]&¶ms[0].toLowerCase()=='all');
if (allCells) params.shift();
var startrow=0; var endrow=row-1;
if (params[0]) var startrow=params.shift();
if (startrow<0) startrow=1*startrow+row; else startrow=startrow-1;
if (params[0]) var endrow=params.shift();
if (endrow<0) endrow=1*endrow+row; else endrow=endrow-1;
var count=total=0;
for (r=startrow; r<=endrow; r++) {
var cell=tbody.childNodes[r].childNodes[col].textContent;
if (!cell) cell=tbody.childNodes[r].childNodes[col].innerHTML; // fallback for older browsers
var val=cell; var hms=cell.split(':');
if (hms.length==3) { // an hh:mm:ss time value
var val=(hms[0]||0)*3600+(hms[1]||0)*60+(hms[2]||0)*1;
var showTime=true; // use time formatting for results...
}
else if (cell.length && !isNaN(cell)) // a numeric value
var val=eval(cell);
else if (allCells) // an non-numeric cell (when 'all' is used)
var val=0;
if (!isNaN(val)) { total+=val; count++; }
}
switch (fn) {
case 'count':
var result=count;
break;
case 'average':
case 'avg':
var result=Math.floor(total/count*100)/100; // truncate to two decimal places
break;
case 'total':
case 'sum':
default:
var result=total;
break;
}
if (showTime && fn!='count') {
var h=Math.floor(result/3600);
var m=Math.floor((result-h*3600)/60);
var s=Math.floor((result-h*3600-m*60)*100)/100; // truncate to two decimal places
result=(h<10?'0':'')+h+':'+(m<10?'0':'')+m+':'+(s<10?'0':'')+s;
}
createTiddlyText(place,result);
}
}
//}}}
/***
|Name|CoreTweaks|
|Source|http://www.TiddlyTools.com/#CoreTweaks|
|Version|use with TW2.4.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.2.0|
|Type|plugin|
|Requires||
|Overrides|various|
|Description|a small collection of overrides to TW core functions|
This tiddler contains small changes to TW core functions that correct or enhance standard features or behavior.
>''Note: the changes contained in this tiddler are generally applicable for version 2.4.3 of TiddlyWiki.''
>Please view [[CoreTweaksArchive]] for tweaks that may be used with earlier versions of TiddlyWiki.
***/
//{{{
// calculate TW version number - used to determine which tweaks should be applied
var ver=version.major+version.minor/10+version.revision/100;
//}}}
/***
----
***/
// // open tickets:
// // {{block{
/***
!!!1134 allow leading whitespace in section headings / TBD handle shadow tiddler sections
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/1134
http://trac.tiddlywiki.org/ticket/TBD
This tweak REPLACES and extends {{{store.getTiddlerText()}}} so it can return sections defined in shadow tiddlers as well as permitting use of leading whitespace in section headings.
***/
//{{{
TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
{
if(!title) return defaultText;
var parts = title.split(config.textPrimitives.sectionSeparator);
var title = parts[0];
var section = parts[1];
var parts = title.split(config.textPrimitives.sliceSeparator);
var title = parts[0];
var slice = parts[1]?this.getTiddlerSlice(title,parts[1]):null;
if(slice) return slice;
var tiddler = this.fetchTiddler(title);
var text = defaultText;
if(this.isShadowTiddler(title))
text = this.getShadowTiddlerText(title);
if(tiddler)
text = tiddler.text;
if(!section) return text;
var re = new RegExp("(^!{1,6}[ \t]*" + section.escapeRegExp() + "[ \t]*\n)","mg");
re.lastIndex = 0;
var match = re.exec(text);
if(match) {
var t = text.substr(match.index+match[1].length);
var re2 = /^!/mg;
re2.lastIndex = 0;
match = re2.exec(t); //# search for the next heading
if(match)
t = t.substr(0,match.index-1);//# don't include final \n
return t;
}
return defaultText;
};
//}}}
// // }}}}}}// // {{block{
/***
!!!890 add conditional test to """<<tiddler>>""" macro
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/890 - OPEN
This tweak extends the {{{<<tiddler>>}}} macro syntax so you can include a javascript-based //test expression// to determine if the tiddler transclusion should be performed:
{{{
<<tiddler TiddlerName if:{{...}} with: param param etc.>>
}}}
If the test is ''true'', then the tiddler is transcluded as usual. If the test is ''false'', then the transclusion is skipped and //no output is produced//.
***/
//{{{
config.macros.tiddler.if_handler = config.macros.tiddler.handler;
config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
params = paramString.parseParams('name',null,true,false,true);
if (!getParam(params,'if',true)) return;
this.if_handler.apply(this,arguments);
};
//}}}
// // }}}}}}// // {{block{
/***
!!!831 backslash-quoting for embedding newlines in 'line-mode' formats
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/831 - OPEN
This tweak pre-processes source content to convert 'double-backslash-newline' into {{{<br>}}} before wikify(), so that literal newlines can be embedded in line-mode wiki syntax (e.g., tables, bullets, etc.)
***/
//{{{
window.coreWikify = wikify;
window.wikify = function(source,output,highlightRegExp,tiddler)
{
if (source) arguments[0]=source.replace(/\\\\\n/mg,'<br>');
coreWikify.apply(this,arguments);
}
//}}}
// // }}}}}}// // {{block{
/***
!!!829 """<<tag>>""" macro - sortby parameter
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/829 - OPEN
This tweak adds an optional 'sortby' parameter to the """<<tag tagname label tip sortby>>""" macro, as well as the """<<allTags excludeTag sortby>>""" macro used to generate the sidebar contents 'tags' list. Specify the field on which the contents of each tag popup is to be sorted, with a '+' or '-' prefix to indicate ascending/descending order, respectively.
Example: """<<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>"""
Try it: <<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>
Similarly, to change the sort order used by the popups from all tags shown in the sidebar contents, edit the [[TagTags]] shadow tiddler and enter: """<<allTags excludeLists -modified>>"""
***/
//{{{
// hijack tag handler() to add 'sortby' attribute to tag button
config.macros.tag.CoreTweaksSortTags_handler=config.macros.tag.handler;
config.macros.tag.handler = function(place,macroName,params)
{
this.CoreTweaksSortTags_handler.apply(this,arguments);
var btn=place.lastChild;
if (params[3]) btn.setAttribute('sortby',params[3]);
}
// tweak <<allTags>> macro to add 'sortby' attribute to each tag button
var fn=config.macros.allTags.handler;
var lines=fn.toString().split('\n');
lines.splice(lines.length-2,0,['if(params[1]) btn.setAttribute("sortby",params[1]);']);
fn=lines.join('\n');
eval('config.macros.allTags.handler='+fn);
// tweak tag event handler to:
// * use tag filtering (only if '[' is present in tag value)
// * use optional 'sortby' attribute
// * save 'sortby' value in 'open all' command (for displaying tiddlers in sorted order)
var fn=onClickTag;
fn=fn.toString().replace(
/store.getTaggedTiddlers\(tag\);/g,
'(tag.indexOf("[")==-1?store.getTaggedTiddlers(tag):store.filterTiddlers(tag));'
+'var sortby=this.getAttribute("sortby");'
+'if(sortby&&sortby.length) store.sortTiddlers(tagged,sortby);'
);
fn=fn.toString().replace(
/openAll.setAttribute\("tag",\s*tag\);/g,
'openAll.setAttribute("tag",tag); openAll.setAttribute("sortby",sortby);'
);
eval(fn);
// tweak 'open all' event handler to use 'sortby' attribute
var fn=onClickTagOpenAll;
fn=fn.toString().replace(
/story.displayTiddlers\(this,\s*tiddlers\);/g,
'var sortby=this.getAttribute("sortby");'
+'if(sortby&&sortby.length) store.sortTiddlers(tiddlers,sortby);'
+'story.displayTiddlers(this,tiddlers);'
);
eval(fn);
//}}}
// // }}}}}}// // {{block{
/***
!!!824 ~WindowTitle - alternative to combined ~SiteTitle/~SiteSubtitle in window titlebar
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/824 - OPEN
This tweak allows definition of an optional [[WindowTitle]] tiddler that, when present, provides alternative text for display in the browser window's titlebar, instead of using the combined text content from [[SiteTitle]] and [[SiteSubtitle]] (which will still be displayed as usual in the TiddlyWiki document header area).
Note: this ticket replaces http://trac.tiddlywiki.org/ticket/401 (closed), which proposed using a custom [[PageTitle]] tiddler for this purpose. ''If you were using the previous '401 ~PageTitle' tweak, you will need to rename [[PageTitle]] to [[WindowTitle]] to continue to use your custom window title text''
***/
//{{{
config.shadowTiddlers.WindowTitle='<<tiddler SiteTitle>> - <<tiddler SiteSubtitle>>';
window.getPageTitle=function() { return wikifyPlain('WindowTitle'); }
store.addNotification('WindowTitle',refreshPageTitle); // so title stays in sync with tiddler changes
//}}}
// // }}}}}}// // {{block{
/***
!!!784 allow tiddler sections in TiddlyLinks to be used as anchor points for intra-tiddler scrolling.
>http://trac.tiddlywiki.org/ticket/784 - OPEN - Please see separate [[SectionLinksPlugin]]
!!!683 FireFox3 Import bug: 'browse' button replacement
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/683 - OPEN
The web standard 'type=file' input control that has been used as a local path/file picker for TiddlyWiki no longer works as expected in FireFox3, which has, for security reasons, limited javascript access to this control so that *no* local filesystem path information can be revealed, even when it is intentional and necessary, as it is with TiddlyWiki. This tweak provides alternative HTML source that patches the backstage import panel. It replaces the 'type=file' input control with a text+button combination of controls that invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
>Note: ''This tweak also requires http://trac.tiddlywiki.org/ticket/604 - cross-platform askForFilename()''
***/
//{{{
if (window.Components) {
var fixhtml='<input name="txtBrowse" style="width:30em"><input type="button" value="..."'
+' onClick="window.browseForFilename(this.previousSibling,true)">';
var cmi=config.macros.importTiddlers;
cmi.step1Html=cmi.step1Html.replace(/<input type='file' size=50 name='txtBrowse'>/,fixhtml);
}
merge(config.messages,{selectFile:'Please enter or select a file'}); // ready for I18N translation
window.browseForFilename=function(target,mustExist) { // note: both params are optional
var msg=config.messages.selectFile;
if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
// get local path for current document
var path=getLocalPath(document.location.href);
var p=path.lastIndexOf('/'); if (p==-1) p=path.lastIndexOf('\\'); // Unix or Windows
if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
var file=''
var result=window.askForFilename(msg,path,file,mustExist); // requires #604
if (target && result.length) // set target field and trigger handling
{ target.value=result; target.onchange(); }
return result;
}
//}}}
// // }}}}}}// // {{block{
/***
!!!604 cross-platform askForFilename()
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/604 - OPEN
invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
***/
//{{{
window.askForFilename=function(msg,path,file,mustExist) {
var r = window.mozAskForFilename(msg,path,file,mustExist);
if(r===null || r===false)
r = window.ieAskForFilename(msg,path,file,mustExist);
if(r===null || r===false)
r = window.javaAskForFilename(msg,path,file,mustExist);
if(r===null || r===false)
r = prompt(msg,path+file);
return r||'';
}
window.mozAskForFilename=function(msg,path,file,mustExist) {
if(!window.Components) return false;
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, mustExist?nsIFilePicker.modeOpen:nsIFilePicker.modeSave);
var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
thispath.initWithPath(path);
picker.displayDirectory=thispath;
picker.defaultExtension='html';
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel)
var result=picker.file.persistentDescriptor;
}
catch(ex) { displayMessage(ex.toString()); }
return result;
}
window.ieAskForFilename=function(msg,path,file,mustExist) {
if(!config.browser.isIE) return false;
try {
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;
return s.showOpen()?s.FileName:'';
}
catch(ex) { displayMessage(ex.toString()); }
return result;
}
window.javaAskForFilename=function(msg,path,file,mustExist) {
if(!document.applets['TiddlySaver']) return false;
// TBD: implement java-based askFile(...) function
try { return document.applets['TiddlySaver'].askFile(msg,path,file,mustExist); }
catch(ex) { displayMessage(ex.toString()); }
}
//}}}
// // }}}}}}// // {{block{
/***
!!!657 wrap tabs onto multiple lines
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/657 - OPEN
This tweak inserts an extra space element following each tab, allowing them to wrap onto multiple lines if needed.
***/
//{{{
config.macros.tabs.handler = function(place,macroName,params)
{
var cookie = params[0];
var numTabs = (params.length-1)/3;
var wrapper = createTiddlyElement(null,'div',null,'tabsetWrapper ' + cookie);
var tabset = createTiddlyElement(wrapper,'div',null,'tabset');
tabset.setAttribute('cookie',cookie);
var validTab = false;
for(var t=0; t<numTabs; t++) {
var label = params[t*3+1];
var prompt = params[t*3+2];
var content = params[t*3+3];
var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,'tab tabUnselected');
createTiddlyElement(tab,'span',null,null,' ',{style:'font-size:0pt;line-height:0px'}); // ELS
tab.setAttribute('tab',label);
tab.setAttribute('content',content);
tab.title = prompt;
if(config.options[cookie] == label)
validTab = true;
}
if(!validTab)
config.options[cookie] = params[1];
place.appendChild(wrapper);
this.switchTab(tabset,config.options[cookie]);
};
//}}}
// // }}}}}}// // {{block{
/***
!!!628 hide 'no such macro' errors
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/628 - OPEN
When invoking a macro that is not defined, this tweak prevents the display of the 'error in macro... no such macro' message. This is useful when rendering tiddler content or templates that reference macros that are defined by //optional// plugins that have not been installed in the current document.
<<option chkHideMissingMacros>> hide 'no such macro' error messages
***/
//{{{
if (config.options.chkHideMissingMacros===undefined)
config.options.chkHideMissingMacros=false;
window.coreTweaks_missingMacro_invokeMacro = window.invokeMacro;
window.invokeMacro = function(place,macro,params,wikifier,tiddler) {
if (!config.macros[macro] || !config.macros[macro].handler)
if (config.options.chkHideMissingMacros) return;
window.coreTweaks_missingMacro_invokeMacro.apply(this,arguments);
}
//}}}
// // }}}}}}// // {{block{
/***
!!!608/609/610 toolbars - toggles, separators and transclusion
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/608 - OPEN (more/less toggle)
http://trac.tiddlywiki.org/ticket/609 - OPEN (separators)
http://trac.tiddlywiki.org/ticket/610 - OPEN (wikify tiddler/slice/section content)
This combination tweak extends the """<<toolbar>>""" macro to add use of '<' to insert a 'less' menu command (the opposite of '>' == 'more'), as well as use of '*' to insert linebreaks and "!" to insert a vertical line separator between toolbar items. In addition, this tweak add the ability to use references to tiddlernames, slices, or sections and render their content inline within the toolbar, allowing easy creation of new toolbar commands using TW content (such as macros, links, inline scripts, etc.)
To produce a one-line style, with "less" at the end, use
| ViewToolbar| foo bar baz > yabba dabba doo < |
resulting in:
{{{
foo bar baz more
and
foo bar baz yabba dabba doo less
}}}
or to use the CoreTweaks? two-line style:
| ViewToolbar| foo bar baz > < * yabba dabba doo |
which would produce:
{{{
foo bar baz more
and
foo bar baz less
yabba dabba doo
}}}
''see [[ToolbarCommands]] for examples of how these features can be used''
***/
//{{{
merge(config.macros.toolbar,{
moreLabel: 'more\u25BC',
morePrompt: 'Show additional commands',
lessLabel: '\u25C4less',
lessPrompt: 'Hide additional commands',
separator: '|'
});
config.macros.toolbar.onClickMore = function(ev) {
var e = this.nextSibling;
e.style.display = 'inline'; // show menu
this.style.display = 'none'; // hide button
return false;
};
config.macros.toolbar.onClickLess = function(ev) {
var e = this.parentNode;
var m = e.previousSibling;
e.style.display = 'none'; // hide menu
m.style.display = 'inline'; // show button
return false;
};
config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
for(var t=0; t<params.length; t++) {
var c = params[t];
switch(c) {
case '!': // ELS - SEPARATOR (added)
createTiddlyText(place,this.separator);
break;
case '*': // ELS - LINEBREAK (added)
createTiddlyElement(place,'BR');
break;
case '<': // ELS - LESS COMMAND (added)
var btn = createTiddlyButton(place,
this.lessLabel,this.lessPrompt,config.macros.toolbar.onClickLess,'moreCommand');
break;
case '>':
var btn = createTiddlyButton(place,
this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore,'moreCommand');
var e = createTiddlyElement(place,'span',null,'moreCommand');
e.style.display = 'none';
place = e;
break;
default:
var theClass = '';
switch(c.substr(0,1)) {
case '+':
theClass = 'defaultCommand';
c = c.substr(1);
break;
case '-':
theClass = 'cancelCommand';
c = c.substr(1);
break;
}
if(c in config.commands)
this.createCommand(place,c,tiddler,theClass);
else { // ELS - WIKIFY TIDDLER/SLICE/SECTION (added)
if (c.substr(0,1)=='~') c=c.substr(1); // ignore leading ~
var txt=store.getTiddlerText(c);
if (txt) {
// trim any leading/trailing newlines
txt=txt.replace(/^\n*/,'').replace(/\n*$/,'');
// trim PRE format wrapper if any
txt=txt.replace(/^\{\{\{\n/,'').replace(/\n\}\}\}$/,'');
// render content into toolbar
wikify(txt,createTiddlyElement(place,'span'),null,tiddler);
}
} // ELS - end WIKIFY CONTENT
break;
}
}
};
//}}}
// // }}}}}}// // {{block{
/***
!!!529 IE fixup - case-sensitive element lookup of tiddler elements
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/529 - OPEN
This tweak hijacks the standard browser function, document.getElementById(), to work-around the case-INsensitivity error in Internet Explorer (all versions up to and including IE7) //''Note: This tweak is only applied when using IE, and only for lookups of rendered tiddler elements within the containing 'tiddlerDisplay' element.''//
***/
//{{{
if (config.browser.isIE) {
document.coreTweaks_coreGetElementById=document.getElementById;
document.getElementById=function(id) {
var e=document.coreTweaks_coreGetElementById(id);
if (!e || !e.parentNode || e.parentNode.id!='tiddlerDisplay') return e;
for (var i=0; i<e.parentNode.childNodes.length; i++)
if (id==e.parentNode.childNodes[i].id) return e.parentNode.childNodes[i];
return null;
};
}
//}}}
// // }}}}}}// // {{block{
/***
!!!471 'creator' field for new tiddlers
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/471 - OPEN
This tweak HIJACKS the core's saveTiddler() function to automatically add a 'creator' field to a tiddler when it is FIRST created. You can use """<<view creator>>""" (or """<<view creator wikified>>""" if you prefer) to show this value embedded directly within the tiddler content, or {{{<span macro="view creator"></span>}}} in the ViewTemplate and/or EditTemplate to display the creator value in each tiddler.
***/
//{{{
// hijack saveTiddler()
TiddlyWiki.prototype.CoreTweaks_creatorSaveTiddler=TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler=function(title,newTitle,newBody,modifier,modified,tags,fields)
{
var existing=store.tiddlerExists(title);
var tiddler=this.CoreTweaks_creatorSaveTiddler.apply(this,arguments);
if (!existing) store.setValue(title,'creator',config.options.txtUserName);
return tiddler;
}
//}}}
// // }}}}}}
// // closed: won't fix //(leave as core tweaks)//
// // {{block{
/***
!!!637 TiddlyLink tooltip - custom formatting
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/637 - CLOSED: WON'T FIX
This tweak modifies the tooltip format that appears when you mouseover a link to a tiddler. It adds an option to control the date format, as well as displaying the size of the tiddler (in bytes)
Tiddler link tooltip format:
{{stretch{<<option txtTiddlerLinkTootip>>}}}
^^where: %0=title, %1=username, %2=modification date, %3=size in bytes, %4=description slice^^
Tiddler link tooltip date format:
{{stretch{<<option txtTiddlerLinkTooltipDate>>}}}
***/
//{{{
config.messages.tiddlerLinkTooltip='%0 - %1, %2 (%3 bytes) - %4';
config.messages.tiddlerLinkTooltipDate='DDD, MMM DDth YYYY 0hh12:0mm AM';
config.options.txtTiddlerLinkTootip=
config.options.txtTiddlerLinkTootip||config.messages.tiddlerLinkTooltip;
config.options.txtTiddlerLinkTooltipDate=
config.options.txtTiddlerLinkTooltipDate||config.messages.tiddlerLinkTooltipDate;
Tiddler.prototype.getSubtitle = function() {
var modifier = this.modifier;
if(!modifier) modifier = config.messages.subtitleUnknown;
var modified = this.modified;
if(modified) modified = modified.formatString(config.options.txtTiddlerLinkTooltipDate);
else modified = config.messages.subtitleUnknown;
var descr=store.getTiddlerSlice(this.title,'Description')||'';
return config.options.txtTiddlerLinkTootip.format([this.title,modifier,modified,this.text.length,descr]);
};
//}}}
// // }}}}}}// // {{block{
/***
!!!607 add HREF link on permaview command
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/607 - CLOSED: WON'T FIX
This tweak automatically sets the HREF for the 'permaview' sidebar command link so you can use the 'right click' context menu for faster, easier bookmarking. Note that this does ''not'' automatically set the permaview in the browser's current location URL... it just sets the HREF on the command link. You still have to click the link to apply the permaview.
***/
//{{{
config.macros.permaview.handler = function(place)
{
var btn=createTiddlyButton(place,this.label,this.prompt,this.onClick);
addEvent(btn,'mouseover',this.setHREF);
addEvent(btn,'focus',this.setHREF);
};
config.macros.permaview.setHREF = function(event){
var links = [];
story.forEachTiddler(function(title,element) {
links.push(String.encodeTiddlyLink(title));
});
var newURL=document.location.href;
var hashPos=newURL.indexOf('#');
if (hashPos!=-1) newURL=newURL.substr(0,hashPos);
this.href=newURL+'#'+encodeURIComponent(links.join(' '));
}
//}}}
// // }}}}}}// // {{block{
/***
!!!458 add permalink-like HREFs on internal TiddlyLinks
***/
// // {{groupbox small{
/***
http://trac.tiddlywiki.org/ticket/458 - CLOSED: WON'T FIX
This tweak assigns a permalink-like HREF to internal Tiddler links (which normally do not have any HREF defined). This permits the link's context menu (right-click) to include 'open link in another window/tab' command. Based on a request from Dustin Spicuzza.
***/
//{{{
window.coreTweaks_createTiddlyLink=window.createTiddlyLink;
window.createTiddlyLink=function(place,title,includeText,theClass,isStatic,linkedFromTiddler,noToggle)
{
// create the core button, then add the HREF (to internal links only)
var link=window.coreTweaks_createTiddlyLink.apply(this,arguments);
if (!isStatic)
link.href=document.location.href.split('#')[0]+'#'+encodeURIComponent(String.encodeTiddlyLink(title));
return link;
}
//}}}
// // }}}}}}
// // <<foldHeadings>>
<script>
var cell=place.parentNode.parentNode.firstChild;
var t=0;
for(var i=0;i<31;i++){
cell=cell.nextSibling;
if(cell.innerHTML=='p' || cell.innerHTML=='P'){
t=t+1;
}
}
wikify(t.toString(),place);
</script>
<script>
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
var classTiddler=store.getTiddler(store.getTiddler(tid).fields.parent);
if(classTiddler==null) return false;
var out= [];
var row="";
var numDays= 31;//assume for now
var students=[];
for(var field in classTiddler.fields){
if(field.match(/^student/)!=null && classTiddler.fields[field]=='true'){
var SID = field.slice(field.match(/^student/)[0].toString().length);
if(!students.inArray(SID)) students.push(SID);
}
}
var strTemplate="<div class=\"toolbar border\" macro=\"toolbar [[ToolbarCommands::EditToolbar]]\"></div>\n" +
"<span macro=\'tiddler ClassRecordsStyleSheet\'></span>"+
"<div class=\"viewer\">" +
"<h1><span macro='view title'>Attendance:</span></h1>"+
"<span macro='tiddler ShowParent'></span><br>"+
"<span macro='edit min'>Minimum Attendance Required: </span>"+
"<table class=\"editRecord\">"+
"<tr><th>SID</th>";
for(var i=1;i<=numDays;i++){
strTemplate=strTemplate+"<th>"+i+"</th>";
}
strTemplate= strTemplate+"</tr>";
for(var i=0;i<students.length;i++){
strTemplate= strTemplate+"<tr><td>"+students[i]+"</td>";
for(var j=1;j<=numDays;j++){
strTemplate=strTemplate+"<td><span macro='edit "+students[i]+"day"+j+" '></span><span macro='tiddler SetMaxLength with:1'></span></td>";
}
strTemplate=strTemplate+"</tr>";
}
strTemplate=strTemplate+"</table></div>";
var templateName = tid+"EditTemplate";
config.shadowTiddlers[templateName]=strTemplate;
</script>
<script>
var testTitle =story.findContainingTiddler(place).getAttribute('tiddler');
var classTitle = store.getValue(testTitle, 'parent');
var classTiddler = store.getTiddler(classTitle);
if(classTiddler==null) return false;
var students = [];
for(field in classTiddler.fields){
if(field.match(/^student/)!=null && classTiddler.fields[field]=='true'){
students.push(field.slice(field.match(/^student/).toString().length));
}
}
var strTemplate="<div class=\"toolbar border\" macro=\"toolbar [[ToolbarCommands::EditToolbar]]\"></div>\n" +
"<h1>Test</h1>"+
"<div class=\"viewer\">" +
"<table class=\"editRecord\">" +
"<tr><td>Name:</td><td><span macro=\"edit title\"></span></td></tr>"+
"<tr><td>Topic(s):</td><td><span macro=\"edit topics\"></span></td></tr>"+
"<tr><td>Maximum Marks:</td><td><span macro=\"edit max_marks\"></span></td></tr>"+
"<tr><td>Pass Marks:</td><td><span macro=\"edit pass_marks\"></span></td></tr>"+
"<tr><td>Date:</td>"+
"<td>"+
"<span macro='select date rows:1 *DatesList'></span>"+
"<span macro='select month rows:1 *MonthsList'></span>"+
"<span macro='select year rows:1 *YearsList'></span>"+
"</td></tr>"+
"</table>"+
"<span style=\"display:none\" macro=\"edit tags\"></span>"+
"<h2>Students Performance</h2>"+
"<table><tr><th>Roll No</th><th>Marks</th><th>Grade</th></tr>\n";
for(var i=0;i<students.length;i++)
strTemplate = strTemplate+"<tr>"+
"<td>"+students[i]+"</td>\n"+
"<td><span macro='edit marks"+students[i]+"'></span></td>\n"+
"<td><span macro='edit grade"+students[i]+"'></span></td>\n"+
"</tr>";
strTemplate=strTemplate+"</table>";
var templateName = testTitle+"EditTemplate";
config.shadowTiddlers[templateName]=strTemplate;
/**********************
var t=story.findContainingTiddler(place).getAttribute('tiddler');
var students = store.getTaggedTiddlers('aStudent');
var enrolled = [];
var classFieldName = 'class'+ store.getValue(t,'parent').toLowerCase();
var testFieldName = 'test'+t.toLowerCase();
for(var s=0;s<students.length;s++)
if(students[s].fields[classFieldName] == 'true')
enrolled.push(students[s]);
//now create a template in a single string
var strTemplate="<div class=\"toolbar border\" macro=\"toolbar [[ToolbarCommands::EditRecordToolbar]]\"></div>\n" +
"<div class=\"title\" macro=\"edit title\">Test Name: </div>\n" +
"<div class=\"viewer\">\n" +
"<table><tr>\n" +
"<td>Maximum Marks:<br><span macro=\"edit max_marks\"></span></td>\n"+
"<td>Pass Marks:<br><span macro=\"edit pass_marks\"></span></td>\n"+
"</tr><tr>\n"+
"<td>Date:<br><span macro=\"edit date\"></span></td>\n"+
"</tr></table>\n"+
"<span style=\"display:none\" macro=\"edit tags\"></span>\n"+
"<h2>Students Performance</h2>\n"+
"<table><tr><th>Roll No</th><th>Marks</th><th>Grade</th></tr>\n";
for(var i=0;i<enrolled.length;i++)
strTemplate = strTemplate+"<tr>"+
"<td>"+enrolled[i].title+"</td>\n"+
"<td><span macro='edit marks"+enrolled[i].title+"'></span></td>\n"+
"<td><span macro='edit grade"+enrolled[i].title+"'></span></td>\n"+
"</tr>";
strTemplate=strTemplate+"</table>";
var templateName = t+"EditTemplate";
config.shadowTiddlers[templateName]=strTemplate;
//store.saveTiddler(templateName,templateName,strTemplate,config.options.txtUserName,new Date(),[],{});
****************************/
</script>
/***
|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|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~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);
}
var t=store.getTiddlerText(linkto,'')
if (config.options.chkInlineCalendarJournals && t.length) wikify('<br>'+t,place);
}
//}}}
|Name|DatePluginInfo|
|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|documentation|
|Requires||
|Overrides||
|Description|documentation for DatePlugin|
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.
!!!!!Usage
<<<
This plugin display formatted dates, for the specified year, month, day using number values or mathematical expressions such as (Y+1) or (D+30). Optionally, you can create a link from the formatted output to a 'dated tiddler' for quick blogging or create a popup menu that includes the dated tiddler link plus links to tiddlers that were created/changed on that date, or are tagged with that date, as well as links to any pending reminders for the coming 31 days (if the RemindersPlugin is installed). This plugin also provides a public API for easily incorporating formatted date output (with or without the links/popups) into other plugins, such as calendar generators, etc.
This plugin defines a macro: {{{<<date [mode] [date] [format] [linkformat]>>}}}. All of the macro parameters are optional and, in it's simplest form, {{{<<date>>}}}, it is equivalent to the ~TiddlyWiki core macro, {{{<<today>>}}}.
However, where {{{<<today>>}}} simply inserts the current date/time in a predefined format (or custom format, using {{{<<today [format]>>}}}), the {{{<<date>>}}} macro's parameters take it much further than that:
* [mode] is either ''display'', ''link'' or ''popup''. If omitted, it defaults to ''display''. This param let's you select between simply displaying a formatted date, or creating a link to a specific 'date titled' tiddler or a popup menu containing a dated tiddler link, plus links to changes and reminders.
* [date] lets you enter ANY date (not just today) as ''year, month, and day values or simple mathematical expressions'' using pre-defined variables, Y, M, and D for the current year, month and day, repectively. You can display the modification date of the current tiddler by using the keyword: ''tiddler'' in place of the year, month and day parameters. Use ''tiddler://name-of-tiddler//'' to display the modification date of a specific tiddler. You can also use keywords ''today'' or ''filedate'' to refer to these //dynamically changing// date/time values.
* [format] and [linkformat] uses standard ~TiddlyWiki date formatting syntax. The default is "YYYY.0MM.0DD"
>^^''DDD'' - day of week in full (eg, "Monday"), ''DD'' - day of month, ''0DD'' - adds leading zero^^
>^^''MMM'' - month in full (eg, "July"), ''MM'' - month number, ''0MM'' - adds leading zero^^
>^^''YYYY'' - full year, ''YY'' - two digit year, ''hh'' - hours, ''mm'' - minutes, ''ss'' - seconds^^
>^^//note: use of hh, mm or ss format codes is only supported with ''tiddler'', ''today'' or ''filedate'' values//^^
* [linkformat] - specify an alternative date format so that the title of a 'dated tiddler' link can have a format that differs from the date's displayed format
In addition to the macro syntax, DatePlugin also provides a public javascript API so that other plugins that work with dates (such as calendar generators, etc.) can quickly incorporate date formatted links or popups into their output:
''{{{showDate(place, date, mode, format, linkformat, autostyle, weekend)}}}''
Note that in addition to the parameters provided by the macro interface, the javascript API also supports two optional true/false parameters:
* [autostyle] - when true, the font/background styles of formatted dates are automatically adjusted to show the date's status: 'today' is boxed, 'changes' are bold, 'reminders' are underlined, while weekends and holidays (as well as changes and reminders) can each have a different background color to make them more visibly distinct from each other.
* [weekend] - true indicates a weekend, false indicates a weekday. When this parameter is omitted, the plugin uses internal defaults to automatically determine when a given date falls on a weekend.
<<<
!!!!!Examples
<<<
The current date: <<date>>
The current time: <<date today "0hh:0mm:0ss">>
Today's blog: <<date link today "DDD, MMM DDth, YYYY">>
Recent blogs/changes/reminders: <<date popup Y M D-1 "yesterday">> <<date popup today "today">> <<date popup Y M D+1 "tomorrow">>
The first day of next month will be a <<date Y M+1 1 "DDD">>
This tiddler (DatePlugin) was last updated on: <<date tiddler "DDD, MMM DDth, YYYY">>
The SiteUrl was last updated on: <<date tiddler:SiteUrl "DDD, MMM DDth, YYYY">>
This document was last saved on <<date filedate "DDD, MMM DDth, YYYY at 0hh:0mm:0ss">>
<<date 2006 07 24 "MMM DDth, YYYY">> will be a <<date 2006 07 24 "DDD">>
<<<
!!!!!Revisions
<<<
2009.05.31 [2.7.1] in addRemindersToPopup(), 'new reminder....' command now uses {{{<<newTiddler>>}}} macro. Also, general code reduction/cleanup.
2008.03.08 [2.7.0] in addModifiedsToPopup(), if a tiddler was created on the specified date, don't list it in the 'changed' section of the popup. Based on a request from Kashgarinn
2008.01.31 [2.6.0] refactored date style logic into separate setDateStyle() function so it can be overridden by a custom definition. See [[DatePluginConfig]].
2008.01.11 [2.5.0] added options to selectively suppress created/changes/tagged/reminders popup content
2008.01.08 [*.*.*] plugin size reduction: documentation moved to DatePluginInfo
2007.11.21 [2.4.0] added hasTagged() and addTaggedToPopup() to list any tiddlers that has been tagged using the title of the dated journal tiddler asa tag value (i.e., the tiddlers that will be listed in the standard "tagging" display when viewing the journal tiddler itself). Based on a request from Coby.
2007.06.20 [2.3.1] in onClickDatePopup(), use Popup.show() instead of deprecated ScrollToTiddlerPopup(). Fixes fatal error that prevents popups from being properly displayed
2007.05.31 [2.3.0] list "created" tiddlers in date popup. Also, force re-cache of created/modified indices when displaying current date and store.isDirty(), so that popup is kept in sync with tiddler changes.
2006.05.09 [2.2.1] added "todaybg" handling to set background color of current date. Also, honor excludeLists tag when getting lists of tiddlers. Based on suggestions by Mark Hulme.
2006.05.05 [2.2.0] added "linkedbg" handling to set background color when a 'dated tiddler' exists. Based on a suggestion by Mark Hulme.
2006.03.08 [2.1.2] add 'override leadtime' flag param in call to findTiddlersWithReminders(), and add "Enter a title" default text to new reminder handler. Thanks to Jeremy Sheeley for these additional tweaks.
2006.03.06 [2.1.0] hasReminders() nows uses window.reminderCacheForCalendar[] when present. If calendar cache is not present, indexReminders() now uses findTiddlersWithReminders() with a 90-day look ahead to check for reminders. Also, switched default background colors for autostyled dates: reminders are now greenish ("c0ffee") and holidays are now reddish ("ffaace").
2006.02.14 [2.0.5] when readOnly is set (by TW core), omit "new reminders..." popup menu item and, if a "dated tiddler" does not already exist, display the date as simple text instead of a link.
2006.02.05 [2.0.4] added var to variables that were unintentionally global. Avoids FireFox 1.5.0.1 crash bug when referencing global variables
2006.01.18 [2.0.3] In 1.2.x the tiddler editor's text area control was given an element ID=("tiddlerBody"+title), so that it was easy to locate this field and programmatically modify its content. With the addition of configuration templates in 2.x, the textarea no longer has an ID assigned. To find this control we now look through all the child nodes of the tiddler editor to locate a "textarea" control where attribute("edit") equals "text", and then append the new reminder to the contents of that control.
2006.01.11 [2.0.2] correct 'weekend' override detection logic in showDate()
2006.01.10 [2.0.1] allow custom-defined weekend days (default defined in config.macros.date.weekend[] array)
added flag param to showDate() API to override internal weekend[] array
2005.12.27 [2.0.0] Update for TW2.0
Added parameter handling for 'linkformat'
2005.12.21 [1.2.2] FF's date.getYear() function returns 105 (for the current year, 2005). When calculating a date value from Y M and D expressions, the plugin adds 1900 to the returned year value get the current year number. But IE's date.getYear() already returns 2005. As a result, plugin calculated date values on IE were incorrect (e.g., 3905 instead of 2005). Adding +1900 is now conditional so the values will be correct on both browsers.
2005.11.07 [1.2.1] added support for "tiddler" dynamic date parameter
2005.11.06 [1.2.0] added support for "tiddler:title" dynamic date parameter
2005.11.03 [1.1.2] when a reminder doesn't have a specified title parameter, use the title of the tiddler that contains the reminder as "fallback" text in the popup menu. Based on a suggestion from BenjaminKudria.
2005.11.03 [1.1.1] Temporarily bypass hasReminders() logic to avoid excessive overhead from generating the indexReminders() cache. While reminders can still appear in the popup menu, they just won't be indicated by auto-styling the date number that is displayed. This single change saves approx. 60% overhead (5 second delay reduced to under 2 seconds).
2005.11.01 [1.1.0] corrected logic in hasModifieds() and hasReminders() so caching of indexed modifieds and reminders is done just once, as intended. This should hopefully speed up calendar generators and other plugins that render multiple dates...
2005.10.31 [1.0.1] documentation and code cleanup
2005.10.31 [1.0.0] initial public release
2005.10.30 [0.9.0] pre-release
<<<
<script>
var out=[];
for(var i=1;i<=31;i++)
out.push(i);
return(out.join("\n"));
</script>
<script>
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
if(tid==null) return false;
var req= store.getValue(tid, 'min');
if(req==undefined) req=0;
req=parseInt(req);
var obt=parseInt(place.parentNode.previousSibling.firstChild.innerHTML);
wikify((req-obt).toString(),place);
</script>
/***
|Name|EditFieldPlugin|
|Source|http://www.TiddlyTools.com/#EditFieldPlugin|
|Version|1.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|extend core edit macro for use in ViewTemplates or direct embedding in tiddler content|
This plugin extends the core {{{<<edit fieldname #OfLines>>}}} macro for use in a ViewTemplate or directly embedded in tiddler content.
!!!!!Usage
<<<
Normally, when you edit a tiddler, any changes you make are saved (or discarded) when you press the "done" (or "cancel") command in the tiddler editor's toolbar. However, when in a 'view mode' context, these command items are not available, and so the TiddlyWiki core commands cannot be used to trigger the 'save/discard' handling once you have decided that your input activities are complete.
This plugin extends the core's input field handling, so that when:
{{{
<<edit fieldname numberOfLines>>
}}}
is used in tiddler content, or:
{{{
<span macro='edit fieldname numberOfLines'></span>
}}}
is used in a ViewTemplate definition, you will be automatically prompted to save/discard your changes (if any) as soon as you press ENTER or move away ('onBlur' handling) from that input field (if the content has been changed). You can also abandon your changes to input field content by pressing ESCAPE (you will be asked to confirm before discarding changes).
You can change the browser-defined default width of an input field by surrounding the edit field by using custom CSS class wrappers, defined in the StyleSheet tiddler. For example:
{{{
.stretch input { width:99%; }
.stretch textarea { width:99%; }
.onechar input { width:1em; }
.twochar input { width:2em; }
.threechar input { width:3em; }
.fourchar input { width:4em; }
.fivechar input { width:5em; }
}}}
>Note: the 'fixed' width values in the above example are only approximate. The actual width rendered by your browser will vary based on the current font-family and font-size that is applied to the field.
<<<
!!!!!Examples
<<<
*"""<<edit foobar>>"""<br> <<edit foobar>>
*"""{{threechar{<<edit foobar>>}}}"""<br> {{threechar{<<edit foobar>>}}}
*"""<<edit tags>>"""<br> <<edit tags>>
*"""{{stretch{<<edit text 10>>}}}"""<br> {{stretch{<<edit text 10>>}}}
<<<
!!!!!Revisions
<<<
2007.08.22 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.EditFieldPlugin= {major: 1, minor: 0, revision: 0, date: new Date(2007,8,22)};
config.macros.edit.editFieldPlugin_savedHandler=config.macros.edit.handler;
config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// let core create edit field
config.macros.edit.editFieldPlugin_savedHandler.apply(this,arguments);
// get edit field or textarea
var fieldType=params[0]=="text"||params[1]?'textarea':'input';
var ins=place.getElementsByTagName(fieldType);
var e=ins[ins.length-1];
if (fieldType=="textarea" && params[1]) e.style.height=params[1]+"em"; // force height for textarea field
// if viewing tiddler, add autosave handlers
var here=story.findContainingTiddler(place);
if (here && here.getAttribute("template").indexOf("ViewTemplate")!=-1) {
story.setDirty(tiddler.title,false); // clear tiddler ("dirty") flag set by core when field was created
var field=e.getAttribute("edit");
var val=store.getValue(tiddler.title,field); if (!val) val="";
e.setAttribute("currval",val); // remember starting value
e.setAttribute("tiddler",tiddler.title); // remember target tiddler
e.onkeydown=function(ev) { // ENTER key=save (for single-line edit fields only)
var event=ev?ev:window.event;
this.setAttribute("keyCode",event.keyCode); // save last keyCode for blur() handler
if (event.keyCode==13 && this.nodeName.toUpperCase()!="TEXTAREA")
this.saveField(); // save input to tiddler field
}
e.onblur=function(ev) { // accept or reject input when focus moves away from field
var event=ev?ev:window.event;
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit");
if (this.value!=this.getAttribute("currval")) { // if value has changed
if (this.getAttribute("keyCode")=="27") { // if user pressed ESC
var msg="Abandon changes to %0@%1?".format([field,tid]);
if (confirm(msg)) this.value=this.getAttribute("currval"); // reset to starting value
this.id=new Date().getTime(); // set unique ID
setTimeout("document.getElementById('"+this.id+"').focus()",1); // restore focus (after blur completes)
} else { // other focus change events
var msg="Save changes to %0@%1?".format([field,tid]);
if (confirm(msg)) this.saveField(); // save input to tiddler field, then continue blur
else this.value=this.getAttribute("currval"); // reset to starting value, then continue blur
}
}
};
e.saveField=function() { // save input value to tiddler field (create, touch or rename tiddler as needed)
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit");
var title=(field=="title")?this.value:tid;
if (!title.length) { // prevent blank tiddler title from being used
this.value=this.getAttribute("currval"); // reset to starting value
this.id=new Date().getTime(); // set unique ID
setTimeout("displayMessage('Please enter a non-blank value')",1); // notify user
setTimeout("document.getElementById('"+this.id+"').focus()",2); // set focus to continue editing
return;
}
var t=store.getTiddler(tid);
store.suspendNotifications();
var anim=config.options.chkAnimate; config.options.chkAnimate=false; // suspend animation
var who=t&&config.options.chkForceMinorUpdate?t.modifier:config.options.txtUserName;
var when=t&&config.options.chkForceMinorUpdate?t.modified:new Date();
store.saveTiddler(t?tid:title,title,t?t.text:"",who,when,t?t.tags:[],t?t.fields:null);
store.setValue(title,field,this.value); // save value in tiddler field
this.setAttribute("currval",this.value); // remember new starting value
if (tid!=title) // if title changed, display renamed tiddler in place of current one
{ story.displayTiddler(story.findContainingTiddler(this),title); story.closeTiddler(tid); }
if (field=="text") // if tiddler content changed, refresh tiddler display
{ story.refreshTiddler(title,null,true); }
config.options.chkAnimate=anim; // resume animation
store.resumeNotifications();
store.notify(title,true);
};
}
}
//}}}
<script>
var students = store.getTaggedTiddlers('aStudent');
var enrolled = [];
var t = story.findContainingTiddler(place).getAttribute('tiddler');
var classFieldName = 'class'+ store.getValue(t,'parent').toLowerCase();
var testFieldName = 'test'+story.findContainingTiddler(place).getAttribute('tiddler').toLowerCase();
var out = [];
console.log(classFieldName + ' ' + testFieldName)
for(var s=0;s<students.length;s++)
if(students[s].fields[classFieldName] == 'true')
enrolled.push(students[s]);
out.push('|!Roll No|!Marks|!Grade|');
for(var i=0;i<enrolled.length;i++)
//out.push('|'+enrolled[i].title+'|<<edit marks'+enrolled[i].title+'>>|<<edit grade'+enrolled[i].title+'>>|');
out.push('|'+enrolled[i].title+'|<<wikify [[%0]] "<<edit marks'+enrolled[i].title+'@here>>" >>|<<wikify [[%0]] "<<edit grade'+enrolled[i].title+'@here>>" >>|');
console.log(out.join('\n'));
return out.join('\n');
</script>
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|interactively select/export tiddlers to a separate file|
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2009.07.06 [2.9.3] moved HTML to section for size reduction
|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: 3, date: new Date(2009,7,6)};
// 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 tiddlers written to %1',
failmsg: 'An error occurred while creating %1',
mergeprompt: '%0\nalready contains tiddlers.\n'
+'\nPress OK to merge new/revised tiddlers into existing file.'
+'\nor, press Cancel to completely replace the file contents',
mergestatus: 'Merged %0 new/revised tiddlers with %1 previously saved tiddlers',
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;
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;
}
},
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 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);
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,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) {
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);
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) {
// 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) && confirm(this.mergeprompt.format([target]))) {
var existing=remoteStore.getTiddlers('title');
for (var i=0; i<existing.length; i++)
if (!titles.contains(existing[i].title))
out.push(this.formatItem(remoteStore,filetype,existing[i],url));
displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
}
}
}
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>
export to path/filename:<br>
<input type="text" id="exportFilename" size=40 style="width:93%"><input
type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%"
onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">
</div>
<!-- output format -->
<div>
output file 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="config.macros.exportTiddlers.process(this)" title="select all tiddlers">
all </a>
<a href="JavaScript:;" id="exportSelectChanges"
onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">
changes </a>
<a href="JavaScript:;" id="exportSelectOpened"
onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">
opened </a>
<a href="JavaScript:;" id="exportSelectRelated"
onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">
related </a>
<a href="JavaScript:;" id="exportToggleFilter"
onclick="config.macros.exportTiddlers.process(this)" title="show/hide selection filter">
filter </a>
</td><td align="right">
<a href="JavaScript:;" id="exportListSmaller"
onclick="config.macros.exportTiddlers.process(this)" title="reduce list size">
– </a>
<a href="JavaScript:;" id="exportListLarger"
onclick="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="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|ExportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for ExportTiddlersPlugin|
interactively select and extract tiddlers from your ~TiddlyWiki document, and write them into another file, using one of several different file formats:
* ~TiddlyWiki - a complete, stand-alone, standard TiddlyWiki HTML document
* ~PureStore - a small HTML archive file containing tiddler data only (no core code)
* ~PlainText - a simple TXT text file with tiddler source listings
* Comma - a "Comma Separated Value" data/spreadsheet file
* ~NewsFeed - an XML-format file that can be published for RSS syndication.
!!!!!Usage
<<<
{{{
<<exportTiddlers>> (sidebar menu item)
<<exportTiddlers inline>> (embedded control panel)
}}}
Inline control panel (live):
<<exportTiddlers inline>>
Optional "special tiddlers" used by this plugin:
* SiteUrl<br>URL for official server-published version of document being viewed (used in XML export). Default: //none//
<<<
!!!!!Revisions
<<<
2009.07.06 [2.9.3] moved HTML to section for size reduction
2009.07.03 [2.9.2] TW252 fixup: don't call convertUTF8ToUnicode() for local loadFile() I/O
2009.04.30 [2.9.1] custom fields in CSV output
2009.04.19 [2.9.0] added CSV format
2009.02.26 [2.8.5] use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.26 [2.8.3] in go(), if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 [2.8.2] in assembleFile(), make sure that markup block is updated if corresponding Markup* tiddler is exported.
2008.09.19 [2.8.1] in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.11 [2.8.0] extensive code cleanup: moved all global functions inside macro object. Re-wrote file generator and I/O to support TiddlyWiki, PlainText, PureStore, and NewsFeed file formats. Replaced inline 'match tags' code with use of getMatchingTiddlers() from [[MatchTagsPlugin]] (if installed), with fallback to core getTaggedTiddlers() otherwise.
2008.05.27 [2.7.0] added ability to 'merge' with existing export file. Also, revised 'matchTags' functionality to be more robust and more efficient
2008.05.12 [2.6.1] automatically add 'export' task to backstage (moved from BackstageTweaks)
2008.03.10 [2.6.0] added "delete tiddlers" button
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.11.10 [2.5.1] removed debugging alert messages from promptForExportFilename()
2007.10.31 [2.5.0] code reduction: removed incomplete/unused interface and supporting functions for exporting directly to http, https or ftp servers. Plugin now supports exporting to local file only. Also, updated TW document output to generate TW2.2 compatible file format.
2007.10.30 [2.4.2] added automatic shadow tiddler definition for [[ExportTiddlers]]
2007.07.16 [2.4.1] in exportTWHeader(), reset HTML source 'markup' so installed markup is NOT copied to new file.
2007.06.30 [2.4.0] added "select related tiddlers" feature. Recursively scans the tiddler links[] info to find all tiddlers referenced by any of the currently selected tiddler, and then selects them all (including the original tiddlers).
2007.04.19 [2.3.0] in exportData(), pass SiteURL value as param to saveToRss(). Fixes 'undefined' appearing in tiddler link in XML output. Also, in refreshExportList(), added 'sort by tags'. Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
2007.03.02 [2.2.6] in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" with fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 [2.2.5] removed hijack of store.saveChanges()
2006.11.08 [2.2.4] added promptForExportFilename() and replaced type="file" control with edit field + browse button ("...").
2006.10.12 [2.2.3] in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format.
2006.05.11 [2.2.2] in createExportPanel, removed call to addNotification() to reduce unneeded feedback messages and increase overall document performance.
2006.05.02 [2.2.1] Use displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection. Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible.
2006.04.29 [2.2.0] New features: free-form "Notes" text inserted in the header of PureStore files.
2006.03.29 [2.1.3] added calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.
2006.02.12 [2.1.2] more FF1501 bug fixes.
2006.02.04 [2.1.1] added var to unintended globals to avoids FireFox1501 crash bug
2006.02.02 [2.1.0] Added support for output of complete TiddlyWiki documents
2006.01.21 [2.0.1] Defer initial panel creation and only register a notification function when panel first is created
in saveChanges 'hijack', create panel as needed. Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.
2005.12.27 [2.0.0] Update for TW2.0.
2005.12.24 [0.9.5] Minor adjustments to CSS to force correct link colors regardless of TW stylesheet selection
2005.12.16 [0.9.4] Dynamically create/remove exportPanel so only one instance exists at a time
2005.11.15 [0.9.2] added non-Ajax post to bypass cross-domain security restrictions.
2005.11.08 [0.9.1] moved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time.
2005.10.28 [0.9.0] added 'select opened tiddlers' feature. Based on a suggestion by Geoff Slocock
2005.10.24 [0.8.3] Corrected hijack of 'save changes' when using http:
2005.10.18 [0.8.2] added AJAX functions
2005.10.18 [0.8.1] Corrected timezone handling and error checking/reporting when filtering tiddlers. More style tweaks, minor text changes and some assorted layout cleanup.
2005.10.17 [0.8.0] First pre-release.
2005.10.16 [0.7.0] filter by tags
2005.10.15 [0.6.0] filter by title/text
2005.10.14 [0.5.0] export to local file (DIV or XML)
2005.10.14 [0.4.0] filter by start/end date
2005.10.13 [0.3.0] panel interaction
2005.10.11 [0.2.0] panel layout
2005.10.10 [0.1.0] code framework
2005.10.09 [0.0.0] development started
<<<
@@display:block;background-color: #636363;color: white;padding:3px; This application has not yet been tested thoroughly. Use with caution and always keep some backup copies of your data.@@
Welcome to ''Class Records'', a tiddlywiki application. If you have been using Tiddlywiki before you can probably figure out everything in under a minute, but for a beginner the following might be useful. Click on the the links below:
#<<slider chkWhatsTW [[Help##Whats A Tiddlywiki]] "Introduction to Tiddlywiki">>
#<<slider chkWhatsTiddler [[Help##Whats A Tiddler]] "Whats a Tiddler?">>
#<<slider chkCRApp [[Help##Class Records Application]] "Class Records Application">>
#<<slider chkCRAppNewClasses [[Help##How to add classes]] "How to add classes">>
#<<slider chkCRAppNewStudents [[Help##How to add students]] "How to add students">>
#<<slider chkCRAppViewClasses [[Help##How to view all classes]] "How to view classes">>
#<<slider chkCRAppViewStudents [[Help##How to view all students]] "How to view students">>
#<<slider chkCRAppSearchig [[Help##Searching]] "Searching">>
#<<slider chkCRAppPrinting [[Help##Printing]] "Printing">>
#<<slider chkAbout [[Help##About]] "About">>
/%
!Whats A Tiddlywiki
@@color:blue;Here is what tiddlywiki's official site says:@@
>~TiddlyWiki is a single html file which has all the characteristics of a wiki - including all of the content, the functionality (including editing, saving, tagging and searching) and the style sheet. Because it's a single file, it's very portable - you can email it, put it on a web server or share it via a USB stick.
>But it's not just a wiki! It has very powerful plugin capabilities, so it can also be used to build new tools. You have full control over how it looks and behaves. For example, ~TiddlyWiki is already being used as:
> * A personal notebook
> * A GTD ("Getting Things Done") productivity tool
> * A collaboration tool
> * For building websites
> * For rapid prototyping
> * ...and much more!
!Whats A Tiddler
A tiddler is a basic data unit in a Tiddlywiki. Everything that is stored in a Tiddlywiki is stored in a Tiddler. You are currently viewing a tiddler named "Help". A Tiddler can contain simple text, formatted text, images, fields, objects such as flash movies etc. Every tiddler needs to have a unique name because Tiddlywiki uses it to ID the tiddler. A Tiddler can be in 2 modes:
*''Edit mode''- in which you can add and edit data of a tiddler.
*''View mode''- in which a tiddler renders its data for view.
To go from a view mode to edit mode click on edit button of the tiddler toolbar on top-right. To come back from edit to view mode you have to click on ''done'' or ''cancel''. You can also ''delete'' a tiddler when it is in edit-mode.
!Class Records Application
In Class Records app you can create classes and students. A Class tiddler can store basic data about itself such as its name, starting date, teacher's name, syllabus and remarks.
A Student tiddler can contain its own set of data items such as name, father's name, mother's name, DOB, date of admission, email etc. A student can be enrolled or dis-enrolled in a class.
You can also create Attendance tiddlers for each month for a Class. Similarly Test tiddlers for a class can also be created which shall contain data related to tests given to that class.
!How to add classes
To add a class click on ''Add Class'' button on the Top Menubar. A new tiddler will be opened in edit mode containing a form. Fill in the form and click ''saveCascade'' to save the record. A new class shall be created and you will be presented with the view mode of the record.
''Note'':-Class name needs to be unique. No other record tiddler, of class or any other should have this name. You might add the session year to the name to make it unique. Do not put a space between the name. You may use character as well as numbers. Usage of camel case style is recommended. eg. ~EngPoetry0809, Punjabi0809, Math0607 ~SpecialEdu0809.
After you have saved the class record, it will be shown in view mode now. In this mode you will see that the class record is composed of 5 sections:
#@@color:green;''Basic data Section''@@- This contains basic data about the class (which you fillled in, in the edit mode)
#@@color:green;''Enrolled Students Section''@@- In this section all the student roll numbers will be displayed in separate tabs according to the year of admission. You can ''enroll'' the students to the current class by simply selecting the checkbox against their roll numbers. Just above the year tabs you will see a summary of the total students and enrolled ones, which of course will change as you enroll or disenroll the students.
#@@color:green;''Attendance Records Section''@@- You can create an ''Attendance Record'' for the class by choosing month and year from the dropdown list and clicking ''Add Attendance'' link on the right. This will create a separate Attendance tiddler. DO NOT CHANGE THE NAME OR ADD ANY DATA AT THIS STAGE. Just click ''done''. After you have done this you can again click ''edit'' to come back to edit mode. Now you can add data of the attendance and click ''done'' again to save the data. You can now come back to the class tiddler and on clicking ''refresh'' on the tiddler toolbar you will be able to see the attendance summary in the Attendance Records Section. All the students who are falling short in their attendance will be mentioned here. You can of course click on names of the attendance or students roll nos to go to their separate tiddlers.
#@@color:green;''Tests Held Section''@@- This section will show the summary of all the tests given for this class. You can add a record of a Test by clicking on ''Add Test'' button. When you are presented with a new Test record tiddler give it a unique name(without spaces, only alphabets and numbers) and click ''done''. DO NOT ADD ANY DATA IN THE TEST TIDDLER JUST NOW. After you have saved the tiddler you can now click edit and this time you will get a form in which you can enter data about the test and marks of students. After you are done with the Test tiddler you can come back to the current Class tiddler, click refresh button in the tiddler toolbar (top right of the tiddler). The newly added Test data shall be shown the Tests Held Section. You can of course click on the name of any test to view its tiddler.
#@@color:green;''Assignments Given Section''@@-
!How to add students
Click on ''Add Student'' on Top Menubar. In the tiddler shown in edit mode enter the details of the student. The ''Student ID'' and ''Date of Admission'' are compulsory fields, you must fill them. THE STUDENT ID NEEDS TO BE UNIQUE, CAN CONTAIN ALPHANUMERIC CHARACTERS AND NO SPACES. The year you fill in the ''Date of Admission'' field will be used to display students year wise in View Students tiddler. Therefore don't forget to fill this in. Click ''done'' and the tiddler will go into view Mode.
Over here you can view the data you just input. On the lower portion of the tiddler you shall see three tabs ''Qualifications'', ''Classes'' and ''Grades''. You can add qualifications(previously obtained before this class) by clicking on ''Add Qualifications'' button just above the tab. This will lead you to another tiddler where you can fill qualification data and then come back to the current student tiddler. You will, of course have to click ''refresh'' link in the tiddler toolbar to see the new qualification here. When this student is enrolled to some class(from some class tiddler), the detail of that class shall be shown here under the ''Classes'' tab. When the student takes some test as part of a class the performance summary shall be displayed here under the ''Grades'' tab.
!How to view all classes
Click on View Classes button on the ~TopMenubar. All the class records shall be displayed under different years in tabs. You can click on any class name to view its individual tiddler.
!How to view all students
Click on View Students button on the ~TopMenubar. All the student records shall be displayed under different years in tabs. You can click on any ~StudentID to view its individual tiddler.
!Searching
!Printing
!About
Tiddlywiki has been created by Jeremy Rustom. This adaptation of Tiddlywiki uses [[UnsavedChangesPlugin]], [[TrashPlugin]], [[TextAreaPlugin]], [[TaggerPlugin]], [[TaggedTemplateTweak]], [[TableSortingPlugin]], [[SnapshotPlugin]], [[SearchOptionsPlugin]], [[RecentChangesPlugin]], [[PasswordOptionsPlugin]], [[ListboxPlugin]], [[InlineJavascriptPlugin]], [[ImportTiddlersPluginPatch]], [[ImportTiddlersPlugin]], [[ExportTiddlersPlugin]], [[EditFieldPlugin]], [[DatePluginConfig]], [[DatePlugin]], [[CoreTweaks]], [[ColumnCalculatorPlugin]], [[CheckboxPlugin]], [[CalendarPlugin]] from [[http://www.tiddlytools.com|http://www.tiddlytools.com/]]
[[TiddlersBarPlugin]] by Pascal Collin from [[http://visualtw.ouvaton.org/VisualTW.html|http://visualtw.ouvaton.org/VisualTW.html]]
Eric Shulman, creator and maintainer of www.tiddlytools.com is the main person who has taught me all the techniques used here. I learn new things from him everytime I approach him. Much obliged.
!end %/
----
The plugins in this package provide interactive functionality for importing/exporting tiddlers to/from other TiddlyWiki documents. Additional plugins provide enhanced local/remote file I/O features, including "save as", "save from web" and "upload" functionality.
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.5.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|config.macros.importTiddlers.handler|
|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
<<<
2009.08.23 4.5.3 in importTiddlers(), add 'file:///' to local server.host sync field only if not already present in URL
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 5, revision: 3, date: new Date(2009,8,23)};
// 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(cmi.css,'importTiddlers');
panel=createTiddlyElement(place,'span','importPanel',null,null)
panel.innerHTML=cmi.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 (config.browser.isGecko) { // 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;
}
//}}}
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
padding: 0.5em; margin:0em; -moz-border-radius:1em;-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; }\
';
//}}}
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
import from\
<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
onclick="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="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="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
all</a>\
<a href="javascript:;" id="importSelectNew"\
onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
added</a>\
<a href="javascript:;" id="importSelectChanges"\
onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
changes</a>\
<a href="javascript:;" id="importSelectDifferences"\
onclick="onClickImportButton(this);return false;" 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="onClickImportButton(this);return false;" title="SHRINK list size">\
– </a>\
<a href="javascript:;" id="importListLarger"\
onclick="onClickImportButton(this);return false;" title="GROW list size">\
+ </a>\
<a href="javascript:;" id="importListMaximize"\
onclick="onClickImportButton(this);return false;" 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:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
>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="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-->\
';
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event) {
var cmi=config.macros.importTiddlers; // abbreviation
var list=cmi.$('importList'); if (!list) return;
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;
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.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|';
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();
var lines=CSV.split('\n'); var names=lines[0].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(/\x22((?:[^\x22]|\x22\x22)*?)\x22/g,
function(x){ return x.substr(1,x.length-2).replace(/\,/g,comma).replace(/\n/g,newline); });
// PARSE lines
var lines=CSV.split('\n');
for (var i=1; i<lines.length; i++) { if (!lines[i].length) continue;
var values=lines[i].split(',');
// DECODE commas, newlines and doubled-quotes within quoted values
for (var v=0; v<values.length; v++)
values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n').replace(/\x22\x22/g,'\x22');
// 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.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)
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;
}
//}}}
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.5.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|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.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 as an optional alternative to the standard import wizard. (Moved from BackstageTweaks).
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, so the plugin control panel is displayed instead of the standard core interface.
2007.06.27 [3.5.5] added missing 'fields' params to saveTiddler() calls. Fixes problem where importing tiddlers would lose the custom fields. Also, moved functions for backward-compatibility with TW2.1.x to separate [[ImportTiddlersPluginPatch2.1.x]] tiddler, reducing the size of //this// plugin tiddler by a significant amount.
2007.06.25 [3.5.4] added calls to store.suspendNotifications() and store.resumeNotifications(). Eliminates redisplay processing overhead DURING import activities
2007.04.29 [3.5.3] if 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" to avoid confusion with "open" button in system-provided Browse... dialog. (i.e., "browse, open, open" becomes "browse, open, 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 for selecting dynamic import source controls in ImportPanel. 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. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.
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. Clear the checkbox to skip this step.
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
<<<
/***
|Name|ImportTiddlersPluginPatch|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPluginPatch|
|Version|4.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|ImportTiddlersPlugin|
|Overrides|config.macros.importTiddlers.handler|
|Description|backward-compatible function patches for use with ImportTiddlersPlugin and TW2.1.x or earlier|
!!!!!Usage
<<<
The current version ImportTiddlersPlugin is compatible with the TW2.2.x core functions. This "patch" plugin provides additional functions needed to enable the current version of ImportTiddlersPlugin to operate correctly under TW2.1.x or earlier.
{{medium{You do not need to install this plugin if you are using TW2.2.0 or above}}}
(though it won't hurt anything if you do... it will just take up more space).
<<<
!!!!!Revisions
<<<
2008.09.30 [4.4.0] added safety check for TW21Loader object and forward-compatible loadFromDiv() prototype to permit use with TW2.0.x and TW1.2.x.
2008.08.05 [4.3.2] rewrote loadRemoteFile to eliminate use of platform-specific fileExists() function
2008.01.03 [3.6.0] added support for passing txtRemoteUsername and txtRemotePassword for accessing password-protected remote servers
2007.06.27 [3.5.5] compatibility functions split from ImportTiddlersPlugin
|please see [[ImportTiddlersPlugin]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
// these functions are only defined when installed in TW2.1.x and earlier...
if (version.major+version.minor/10 <= 2.1) {
// Version
version.extensions.ImportTiddlersPluginPatch= {major: 4, minor: 4, revision: 0, date: new Date(2008,9,30)};
// fixups for TW2.0.x and earlier
if (window.merge==undefined) window.merge=function(dst,src,preserveExisting)
{ for (p in src) if (!preserveExisting||dst[p]===undefined) dst[p]=src[p]; return dst; }
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={ };
config.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet) {
if (src==undefined || !src.length) return null; // filename is required
if (!quiet) clearMessage();
if (!quiet) displayMessage(this.openMsg.format([src]));
if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if 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
if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
} else {
if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
if (callback) callback(true,src,convertUTF8ToUnicode(txt),src,null);
}
} else {
var x; // get an request object
try {x = new XMLHttpRequest()} // moz
catch(e) {
try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6
catch (e) {
try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5
catch (e) { return }
}
}
// setup callback function to handle server response(s)
x.onreadystatechange = function() {
if (x.readyState == 4) {
if (x.status==0 || x.status == 200) {
if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([x.responseText.length,src]));
if (callback) callback(true,src,x.responseText,src,x);
}
else {
if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,x.status]));
}
}
}
// get privileges to read another document's DOM via http:// or file:// (moz-only)
if (typeof(netscape)!="undefined") {
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
}
// send the HTTP request
try {
var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
x.open("GET",src,true,config.options.txtRemoteUsername,config.options.txtRemotePassword);
if (x.overrideMimeType) x.overrideMimeType('text/html');
x.send(null);
}
catch (e) {
if (!quiet) {
displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(unknown)"]));
displayMessage(e.description?e.description:e.toString());
}
}
}
}
config.macros.importTiddlers.readTiddlersFromHTML=function(html) {
// for TW2.1 and earlier
// extract store area from html
var start=html.indexOf('<div id="storeArea">');
var end=html.indexOf("<!--POST-BODY-START--"+">",start);
if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents
var sa="<html><body>"+html.substring(start,end)+"</body></html>";
// load html into iframe document
var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);
f=document.createElement("iframe"); f.id="loaderFrame";
f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
document.body.appendChild(f);
var d=f.document;
if (f.contentDocument) d=f.contentDocument; // For NS6
else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
d.open(); d.writeln(sa); d.close();
// read tiddler DIVs from storeArea DOM element
var sa = d.getElementById("storeArea");
if (!sa) return null;
sa.normalize();
var nodes = sa.childNodes;
if (!nodes || !nodes.length) return null;
var tiddlers = [];
for(var t = 0; t < nodes.length; t++) {
var title = null;
if(nodes[t].getAttribute)
title = nodes[t].getAttribute("title"); // TW 2.2+
if(!title && nodes[t].getAttribute)
title = nodes[t].getAttribute("tiddler"); // TW 2.1.x
if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))
title = nodes[t].id.substr(5); // TW 1.2.x
if(title && title != "")
tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));
}
return tiddlers;
}
// // FORWARD-COMPATIBLE SUPPORT FOR TW2.1.x
// // enables reading tiddler definitions using TW2.2+ storeArea format, even when plugin is running under TW2.1.x
if (typeof TW21Loader!="undefined") {
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node) {
var e = node.firstChild;
var text = null;
if(node.getAttribute("tiddler"))
text = getNodeText(e).unescapeLineBreaks();
else {
while(e.nodeName!="PRE" && e.nodeName!="pre") e = e.nextSibling;
text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
}
var modifier = node.getAttribute("modifier");
var c = node.getAttribute("created");
var m = node.getAttribute("modified");
var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
var tags = node.getAttribute("tags");
var fields = {};
var attrs = node.attributes;
for(var i = attrs.length-1; i >= 0; i--) {
var name = attrs[i].name;
if (attrs[i].specified && !TiddlyWiki.isStandardField(name))
fields[name] = attrs[i].value.unescapeLineBreaks();
}
tiddler.assign(title,text,modifier,modified,tags,created,fields);
return tiddler;
};
}
// FORWARD-COMPATIBLE SUPPORT FOR TW2.0.x and TW1.2.x
// enables reading tiddler definitions using TW2.2+ storeArea format, even when plugin is running under TW2.0.x or TW1.2.x
if (typeof Tiddler.prototype.loadFromDiv!="undefined") {
Tiddler.prototype.loadFromDiv = function(node,title) { // Load a tiddler from an HTML DIV
var e = node.firstChild;
var text = null;
if(node.getAttribute("tiddler")) {
// get merged text from adjacent text nodes
var t=""; while(e&&e.nodeName=="#text") { t+=e.nodeValue; e=e.nextSibling; }
text = Tiddler.unescapeLineBreaks(t);
} else {
while(e.nodeName!="PRE" && e.nodeName!="pre") e = e.nextSibling;
text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
}
var modifier = node.getAttribute("modifier");
var c = node.getAttribute("created");
var m = node.getAttribute("modified");
var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
var tags = node.getAttribute("tags");
this.set(title,text,modifier,modified,tags,created);
return this;
}
}
} // END OF pre-TW2.2 backward-compatibility functions
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // external script library
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // inline code
if (show) // display source in tiddler
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create 'onclick' command link
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run script immediately
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name|InlineJavascriptPluginInfo|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for InlineJavascriptPlugin|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Usage
<<<
This plugin adds wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be recognized as embedded javascript code.
<script show>
/* javascript code goes here... */
</script>Every time the tiddler content is rendered, the javascript code is automatically evaluated, allowing you to invoke 'side-effect' processing and/or produce dynamically-generated content that is then inserted into the tiddler content, immediately following the script (see below). By including the optional ''show'' keyword as the final parameter in a {{{<script>}}} marker, the plugin will also include the script source code in the output that it displays in the tiddler. This is helpful when creating examples for documentation purposes (such as used in this tiddler!)
__''Deferred execution from an 'onClick' link''__
<script label="click here" title="mouseover tooltip text" key="X" show>
/* javascript code goes here... */
alert('you clicked on the link!');
</script>
By including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered. You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text, and a {{{key="X"}}} parameter to specify an //access key// (which must be a //single// letter or numeric digit only).
__''Loading scripts from external source files''__
<script src="URL" show>
/* optional javascript code goes here... */
</script>You can also load javascript directly from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.
In addition to loading the javascript from the external file, you can also use this feature to invoke javascript code contained within the {{{<script>...</script>}}} markers. This code is invoked //after// the external script file has been processed, and can make immediate use of the functions and/or global variables defined by the external script file.
>Note: To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that is rendered as soon as your TiddlyWiki document is opened, such as MainMenu. For example: put your {{{<script src="..."></script>}}} syntax into a separate 'library' tiddler (e.g., LoadScripts), and then add {{{<<tiddler LoadScripts>>}}} to MainMenu so that the library is loaded before any other tiddlers that rely upon the functions it defines.
>
>Normally, loading external javascript in this way does not produce any direct output, and should not have any impact on the appearance of your MainMenu. However, if your LoadScripts tiddler contains notes or other visible content, you can suppress this output by using 'inline CSS' in the MainMenu, like this: {{{@@display:none;<<tiddler LoadScripts>>@@}}}
<<<
!!!!!Creating dynamic tiddler content and accessing the ~TiddlyWiki DOM
<<<
An important difference between TiddlyWiki inline scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document: in a typical web document, you use the {{{document.write()}}} (or {{{document.writeln()}}}) function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.
However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and instead will //completely replace the entire ~TiddlyWiki document in your browser window (which is clearly not a good thing!)//. In order to allow scripts to use {{{document.write()}}}, the plugin automatically converts and buffers all HTML output so it can be safely inserted into your tiddler content, immediately following the script.
''Note that {{{document.write()}}} can only be used to output "pure HTML" syntax. To produce //wiki-formatted// output, your script should instead return a text value containing the desired wiki-syntax content'', which will then be automatically rendered immediately following the script. If returning a text value is not sufficient for your needs, the plugin also provides an automatically-defined variable, 'place', that gives the script code ''direct access to the //containing DOM element//'' into which the tiddler output is being rendered. You can use this variable to ''perform direct DOM manipulations'' that can, for example:
* generate wiki-formatted output using {{{wikify("...content...",place)}}}
* vary the script's actions based upon the DOM element in which it is embedded
* access 'tiddler-relative' DOM information using {{{story.findContainingTiddler(place)}}}
Note:
''When using an 'onclick' script, the 'place' element actually refers to the onclick //link text// itself, instead of the containing DOM element.'' This permits you to directly reference or modify the link text to reflect any 'stateful' conditions that might set by the script. To refer to the containing DOM element from within an 'onclick' script, you can use "place.parentNode" instead.
<<<
!!!!!Instant "bookmarklets"
<<<
You can also use an 'onclick' link to define a "bookmarklet": a small piece of javascript that can be ''invoked directly from the browser without having to be defined within the current document.'' This allows you to create 'stand-alone' commands that can be applied to virtually ANY TiddlyWiki document... even remotely-hosted documents that have been written by others!! To create a bookmarklet, simply define an 'onclick' script and then grab the resulting link text and drag-and-drop it onto your browser's toolbar (or right-click and use the 'bookmark this link' command to add it to the browser's menu).
Notes:
*When writing scripts intended for use as bookmarklets, due to the ~URI-encoding required by the browser, ''you cannot not use ANY double-quotes (") within the bookmarklet script code.''
*All comments embedded in the bookmarklet script must ''use the fully-delimited {{{/* ... */}}} comment syntax,'' rather than the shorter {{{//}}} comment syntax.
*Most importantly, because bookmarklets are invoked directly from the browser interface and are not embedded within the TiddlyWiki document, there is NO containing 'place' DOM element surrounding the script. As a result, ''you cannot use a bookmarklet to generate dynamic output in your document,'' and using {{{document.write()}}} or returning wiki-syntax text or making reference to the 'place' DOM element will halt the script and report a "Reference Error" when that bookmarklet is invoked.
Please see [[InstantBookmarklets]] for many examples of 'onclick' scripts that can also be used as bookmarklets.
<<<
!!!!!Special reserved function name
<<<
The plugin 'wraps' all inline javascript code inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.
<<<
!!!!!$(...) 'shorthand' function
<<<
As described by Dustin Diaz [[here|http://www.dustindiaz.com/top-ten-javascript/]], the plugin defines a 'shorthand' function that allows you to write:
{{{
$(id)
}}}
in place of the normal standard javascript syntax:
{{{
document.getElementById(id)
}}}
This function is provided merely as a convenience for javascript coders that may be familiar with this abbreviation, in order to allow them to save a few bytes when writing their own inline script code.
<<<
!!!!!Examples
<<<
simple dynamic output:
><script show>
document.write("The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
if (!window.story) window.story=window;
var title=story.findContainingTiddler(place).getAttribute("tiddler");
var size=store.getTiddlerText(title).length;
return title+" is using "+size+" bytes";
</script>
dynamic output from an 'onclick' script, using {{{document.write()}}} and/or {{{return "..."}}}
><script label="click here" show>
document.write("<br>The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
creating an 'onclick' button/link that accesses the link text AND the containing tiddler:
><script label="click here" title="clicking this link will show an 'alert' box" key="H" show>
if (!window.story) window.story=window;
var txt=place.firstChild.data;
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
alert('Hello World!\nlinktext='+txt+'\ntiddler='+tid);
</script>
dynamically setting onclick link text based on stateful information:
>{{block{
{{{
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.previousSibling.innerHTML=on?"disable":"enable";
</script>
}}}
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.innerHTML=on?"enable":"disable";
</script>
}}}
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function inlineJavascriptDemo() { alert('Hello from demo.js!!') } }}}
>>{{{displayMessage('InlineJavascriptPlugin: demo.js has been loaded');}}}
>note: When using this example on your local system, you will need to download the external script file from the above URL and install it into the same directory as your document.
>
><script src="demo.js" show>
return "inlineJavascriptDemo() function has been defined"
</script>
><script label="click to invoke inlineJavascriptDemo()" key="D" show>
inlineJavascriptDemo();
</script>
<<<
!!!!!Revisions
<<<
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
2008.06.11 [1.9.3] added $(...) function as 'shorthand' for document.getElementById()
2008.03.03 [1.9.2] corrected fallback declaration of wikifyPlainText() (fixes Safari "parse error")
2008.02.23 [1.9.1] in onclick function, use string instead of array for 'bufferedHTML' (fixes IE errors)
2008.02.21 [1.9.0] output from 'onclick' scripts (return value or document.write() calls) are now buffered and rendered into into a span following the script. Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed). Thanks to Xavier Verges for suggestion and preliminary code.
2008.02.14 [1.8.1] added backward-compatibility for use of wikifyPlainText() in TW2.1.3 and earlier
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 [1.8.0] added support for key="X" syntax to specify custom access key definitions
2007.12.15 [1.7.0] autogenerate URI encoded HREF on links for onclick scripts. Drag links to browser toolbar to create bookmarklets. IMPORTANT NOTE: place is NOT defined when scripts are used as bookmarklets. In addition, double-quotes will cause syntax errors. Thanks to PaulReiber for debugging and brainstorming.
2007.11.26 [1.6.2] when converting "document.write()" function calls in inline code, allow whitespace between "write" and "(" so that "document.write ( foobar )" is properly converted.
2007.11.16 [1.6.1] when rendering "onclick scripts", pass label text through wikifyPlainText() to parse any embedded wiki-syntax to enable use of HTML entities or even TW macros to generate dynamic label text.
2007.02.19 [1.6.0] added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
2006.10.16 [1.5.2] add newline before closing '}' in 'function out_' wrapper. Fixes error caused when last line of script is a comment.
2006.06.01 [1.5.1] when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly
2006.04.19 [1.5.0] added 'show' parameter to force display of javascript source code in tiddler output
2006.01.05 [1.4.0] added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.
2005.12.13 [1.3.1] when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski
2005.11.09 [1.3.0] for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck
2005.11.08 [1.2.0] handle loading of javascript from an external URL via src="..." syntax
2005.11.08 [1.1.0] pass 'place' param into scripts to provide direct DOM access
2005.11.08 [1.0.0] initial release
<<<
<script>
var attendances=store.getTaggedTiddlers('Attendance');
var out=[];
var classTitle= story.findContainingTiddler(place).getAttribute('tiddler');
out.push("|<<autosort>>Attendance|Summary|h");
for(var a=0;a<attendances.length;a++){
if(attendances[a].fields.parent && attendances[a].fields.parent == classTitle){
var t=attendances[a].title; var mnth= t.substring(0,3); var yr=t.substring(3,7); var dt=(mnth+' 1, '+yr).toString();
out.push('|[['+dt+'|'+attendances[a].title+']]|<<tiddler ShowAttendanceSummary with:\"'+attendances[a].title+'\">>|');
}
}
out.push('|sortable|k');
wikify(out.join('\n'),place);
</script>
<script>
var tests= store.getTaggedTiddlers('Test');
var childTests= [];
var classTitle= story.findContainingTiddler(place).getAttribute('tiddler');
for(var t=0;t<tests.length;t++)
if(tests[t].fields.parent && tests[t].fields.parent == classTitle)
childTests.push('#[['+tests[t].title+']] held on '+tests[t].fields.date+'/'+tests[t].fields.month+'/'+tests[t].fields.year+' on the topics: '+tests[t].fields.topics);
wikify(childTests.join('\n'),place);
</script>
/***
|Name|ListboxPlugin|
|Source|http://www.TiddlyTools.com/#ListboxPlugin|
|Documentation|http://www.TiddlyTools.com/#ListboxPluginInfo|
|Version|1.2.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|set tiddler fields by selecting from a listbox or droplist|
The {{{<<select>>}}} macro allows you to set tiddler field values by selecting pre-configured values from a listbox/droplist control.
!!!!!Documentation
>see [[ListboxPluginInfo]]
!!!!!Revisions
<<<
2009.06.15 [1.2.3] in setFieldValue(), eliminate extra tiddly brackets around single value selections
|please see [[ListboxPluginInfo]] for additional revision details|
2007.05.12 [0.5.0] started
<<<
!!!!!Code
***/
//{{{
version.extensions.ListboxPlugin= {major: 1, minor: 2, revision: 3, date: new Date(2009,6,15)};
config.macros.select = {
tooltip: "select a value for %0@%1",
blankTooltip: "set %0@%1=[no value]",
valueTooltip: "set %0@%1=%2",
otherLabel: "other",
otherTooltip: "set %0@%1=[enter a value...]",
otherPrompt: "enter a value for '%0'",
editLabel: "edit list...",
editTooltip: "edit '%0' list definition (%1)",
changeMsg: "setting %0@%1=%2",
verbose: false,
hereKeyword: "here",
defaultTarget: "SiteFields",
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
// default to containing tiddler or "SiteFields" catch-all
var here=story.findContainingTiddler(place);
var targetID=here?here.getAttribute("tiddler"):this.defaultTarget;
// get field name and non-default target (if any)
var field=params.shift();
var pos=field.indexOf("@"); // if non-default target ("field@tiddler" syntax)
if(pos!=-1) { // split field into field and tiddlername.
if (field.substr(pos+1)!=this.hereKeyword) // "here" == use default target
targetID=field.substr(pos+1); // use different target tiddler
field=field.substr(0,pos);
}
if(!field || !field.length) return; // no field name... do nothing
if (field.substr(0,1)=="=") targetID="(system)"; // internal option value
var items=[]; var listsrc='';
var autosave=false; var allowBlank=false; var allowOther=false; var allowEdit=false;
var allowMultiple=false; var wikifyData=false; var rows=0; var width='';
var p=params.shift();
while (p) {
if (p.toLowerCase()=='autosave') // autosave on change
autosave=true;
else if (p.toLowerCase()=='allowblank') // add empty item
var allowBlank=true;
else if (p.toLowerCase()=='allowother') // add "other: ____" item
var allowOther=true;
else if (p.toLowerCase()=='allowedit') // add "edit list..." item
var allowEdit=true;
else if (p.toLowerCase()=='allowmultiple') // multi-select
var allowMultiple=true;
else if (p.startsWith('rows:')) // 0=autosize listbox, 1=droplist, n=listbox
var rows=p.substr(5);
else if (p.startsWith('width:')) // CSS width of list
var width=p.substr(6);
else if (p.substr(0,1)=="+"||p.substr(0,1)=="*") { // read HR-separated tiddler
var listsrc=p.substr(1);
var listtxt=store.getTiddlerText(listsrc,'');
var wikifyData=p.substr(0,1)=="*";
if (listtxt.length && wikifyData) // wikify source to handle macros/scripts
listtxt=this.getWikifiedData(listtxt);
if (listtxt.length)
items=items.concat(listtxt.split(listtxt.indexOf('\n----\n')!=-1?'\n----\n':'\n'));
}
else if (p.substr(0,1)=="=") { // get items from tagged tiddlers
var tids=store.getTaggedTiddlers(p.substr(1));
for (var t=0; t<tids.length; t++) items.push(tids[t].title);
}
else { // param is item value or 'label=value'
var parts=p.split("=");
var label=parts[0]; var v=parts[1]?parts[1]:parts[0];
items.push(label+"="+v);
}
p=params.shift();
}
if (rows==1) allowMultiple=false; // droplist cannot do multi-select
if (tiddler && !story.isDirty(tiddler.title)) autosave=true; // tiddler is in VIEW mode, force autosave
this.render(createTiddlyElement(place,"span"), null,
targetID, field, items, listsrc, wikifyData,
rows, width, autosave, allowBlank, allowOther, allowEdit, allowMultiple);
store.addNotification(null,this.refresh); // syncs lists when tiddlers are changed
},
getWikifiedData: // wikify tiddler content, then extract text WITH newlines and HRs included
function(txt) {
var e=createTiddlyElement(document.body,"div"); wikify(txt,e);
var breaks=e.getElementsByTagName("br");
for (var b=0; b<breaks.length; b++) breaks[b].parentNode.insertBefore(document.createTextNode("\n"),breaks[b]);
var lines=e.getElementsByTagName("hr");
for (var l=0; l<lines.length; l++) lines[l].parentNode.insertBefore(document.createTextNode("----\n"),lines[l]);
var items=e.getElementsByTagName("li");
for (var i=0; i<items.length; i++) items[i].parentNode.insertBefore(document.createTextNode("\n"),items[i]);
var txt=getPlainText(e); removeNode(e); return txt;
},
refresh:
function (title) { // re-render dependent lists
var lists=document.getElementsByTagName('select');
for (var i=0; i<lists.length; i++) { var list=lists[i];
if (list.getAttribute('listsrc')!=title) continue; // no sync needed
var listtxt=store.getTiddlerText(list.getAttribute('listsrc')||'','');
if (listtxt.length && list.getAttribute("wikifyData")=="true")
listtxt=this.getWikifiedData(listtxt);
if (listtxt.length)
var items=listtxt.split(listtxt.indexOf('\n----\n')!=-1?'\n----\n':'\n');
config.macros.select.render(list.parentNode, list,
list.getAttribute('tiddler'), list.getAttribute('edit'),
items||[], list.getAttribute('listsrc'),
list.getAttribute("wikifyData")=="true",
list.getAttribute("rows"),
list.getAttribute("width"),
list.getAttribute("autosave")=="true",
list.getAttribute("allowBlank")=="true",
list.getAttribute("allowOther")=="true",
list.getAttribute("allowEdit")=="true",
list.getAttribute("allowMultiple")=="true");
}
},
render:
function (place, here, targetID, field, items, listsrc, wikifyData,
rows, width, autosave, allowBlank, allowOther, allowEdit, allowMultiple) {
var values=[]; var opts=[];
// use current selection(s) (if any) (except for "edit list..." item)
if (here) for (var i=0; i<here.options.length; i++) {
var opt=here.options[i];
if (opt.selected && opt.text!=config.macros.select.editLabel) values.push(opt.value);
}
// no listbox or no selections... get value(s) from field (if any)
if (!values.length) {
var v=(field.substr(0,1)=='=')?config.options[field.substr(1)]:store.getValue(targetID,field);
if (v) values=!allowMultiple?[v]:v.toString().readBracketedList();
}
// add 'no value' item
if (!values.length || allowBlank)
opts.push('<option value="" title="'+this.blankTooltip.format([field,targetID])+'"></option>');
// add enumerated items
var isOther=values.length; // assume no matching value
for (var opt=0; opt<items.length; opt++) {
var lines=items[opt].split("\n"); var parts=lines[0].split("=");
var label=parts[0];
var v=parts[1]?parts[1]:parts[0];
var title=lines[1]?lines[1]:this.valueTooltip.format([field,targetID,v]);
var sel=values.contains(v); if (sel) isOther=false; // found matching value
opts.push('<option value="'+v+'" '+(sel?'selected':'')+' title="'+title+'">'+label+'</option>');
}
// add 'other...'
if (isOther||allowOther) {
var label="other"+(isOther?(": "+values[0]):"...");
var v=isOther?values[0]:'';
var t=this.otherTooltip.format([field,targetID]);
opts.push('<option value="'+v+'" '+(isOther?'selected':'')+' title="'+t+'">'+label+'</option>');
}
// add 'edit list...'
if (listsrc && (!store.getTiddlerText(listsrc) || allowEdit)) {
var title=this.editTooltip.format([field,listsrc]);
opts.push('<option value="'+listsrc+'" title="'+title+'">'+this.editLabel+'</option>');
}
// render listbox
var html='<select '+(values[0]?'value="'+values[0]+'" ':' ')
+' title="'+this.tooltip.format([field,targetID])+'"'
+' rows="'+rows+'"'+' size="'+(rows!=0?rows:opts.length)+'"'+' style="width:'+width+'"'
+' tiddler="'+targetID+'"'+' edit="'+field+'"'+' listsrc="'+listsrc+'"'+' wikifyData="'+wikifyData+'"'
+' autosave="'+autosave+'"'+' allowBlank="'+allowBlank+'"'+' allowOther="'+allowOther+'"'
+' allowEdit="'+allowEdit+'"'+' allowMultiple="'+allowMultiple+'"'+(allowMultiple?' multiple':'')
+' onclick="return config.macros.select.onClick(this,event)"'
+' onchange="return config.macros.select.onChange(this,event)"'
+' ondblclick="return false">'+opts.join('')+'</select>';
place.innerHTML=html;
},
onClick:
function(here,event) {
var label=config.macros.select.otherLabel;
if (here.getAttribute("allowother")=="true" && here.options[here.selectedIndex].text.substr(0,label.length)==label)
here.onchange.apply(here,arguments);
},
onChange:
function(here,event) {
if (here.options[here.selectedIndex].text==config.macros.select.editLabel) {
story.displayTiddler(story.findContainingTiddler(here),here.value,DEFAULT_EDIT_TEMPLATE);
return false;
}
var label=config.macros.select.otherLabel;
if (here.getAttribute("allowother")=="true" && here.options[here.selectedIndex].text.substr(0,label.length)==label) {
var newval=prompt(config.macros.select.otherPrompt.format([here.getAttribute("edit")]),here.value);
if (!newval) {// user cancelled
var v=store.getValue(here.getAttribute("tiddler"),here.getAttribute("edit"));
{ here.value=v; if (v==undefined) here.selectedIndex=0; return false; }
};
here.options[here.selectedIndex].value=newval;
here.options[here.selectedIndex].text=config.macros.select.otherLabel+": "+newval;
here.value=newval;
}
if (here.getAttribute("autosave")=="true") config.macros.select.setFieldValue(here);
return false;
},
setFieldValue: function(here) {
var tid=here.getAttribute("tiddler"); if (!tid || !tid.length) return; // no target, do nothing
var field=here.getAttribute("edit");
if (field.substr(0,1)=='=') { // option cookie instead of tiddler field
config.macros.option.propagateOption(field.substr(1),"value",here.value,"input");
return;
}
// ensure tiddler exists
if (!store.tiddlerExists(tid)) store.saveTiddler(tid,tid,"",config.options.txtUserName,new Date(),[]);
// get multi-select items
var values=[]; for (var i=0; i<here.options.length; i++) { var opt=here.options[i];
if (opt.selected && opt.text!=config.macros.select.editLabel)
values.pushUnique(String.encodeTiddlyLink(opt.value));
}
if (values.length==1) values=[here.value]; // remove extra brackets around single value
// set field, 'touch' tiddler and report to user
store.setValue(tid,field,values.length?values.join(' '):null); // if no selections, delete field
var t=store.getTiddler(tid);
store.saveTiddler(tid,tid,t.body,config.options.txtUserName,new Date(),t.tags,t.fields);
if (config.macros.select.verbose)
{ clearMessage(); displayMessage(config.macros.select.changeMsg.format([field,tid,here.value])); }
}
}
//}}}
|Name|ListboxPlugin|
|Source|http://www.TiddlyTools.com/#ListboxPlugin|
|Documentation|http://www.TiddlyTools.com/#ListboxPluginInfo|
|Version|1.2.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for ListboxPlugin|
The {{{<<select>>}}} macro allows you to set tiddler field values by selecting pre-configured enumerated values from a listbox/droplist control.
!!!!!Usage
<<<
in tiddler content:
{{{
<<select fieldname@tiddlername value value value ...
rows:nn width:xxx autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername label=value label=value label=value ...
rows:nn width:xxx autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername =TiddlerName allowEdit
rows:nn width:xxx autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername +TiddlerName allowEdit
rows:nn width:xxx autoSave allowBlank allowOther allowMultiple>>
}}}
in a custom [[EditTemplate]] or [[ViewTemplate]]:
{{{
<div class="editor" macro="select ..."></div>
}}}
//where://
*''fieldname@tiddlername'' (or ''=cookiename'')<br>specifies the tiddler field associated with the list display. The "@tiddlername" portion is optional and, when omitted (or the special keyword, "@here" is used), the current tiddler is assumed. Alternatively, if the fieldname begins with an equal sign (=), then it will be used as a TiddlyWiki option cookie reference and the selected value will be ''assigned to that cookiename //instead// of being stored in a tiddler field''. Note: when a cookie reference is used, any "@tiddlername" portion that may be present in the syntax will be //ignored//.
*''value value value ...'' //or// ''label=value label=value label=value ...'' //(inline list definition)// //or// ''=tagvalue'' //(tag-based list definition)// //or// ''+~TiddlerName'' //or// ''*~TiddlerName'' //(tiddler-based list definition)//<br>specifies list item values or label/value pairs. You can use the ''=tagvalue'' syntax to generate a list whose items are the names of tiddlers tagged with that value (e.g., "=systemConfig" to list all plugins, or "=friends" to list all tiddlers tagged as "friends"). You can also use the ''+~TiddlerName'' or ''*~TiddlerName'' syntax to define the values or label/value pairs using a tiddler containing an "HR-separated" list, where each list item is one or two lines of text, separated from the next item by a horizontal rule: """----""". The first line of each item contains the value or label=value that will appear in the list. The second, optional line allows you to specify a custom tooltip for that list item. If you use "*" preceding the ~TiddlerName, the contents of the tiddler will be processed by the TiddlyWiki parser before being processed as a list definition. This allows you to use macros to dynamically generate list definitions based on the current document contents (such as available tag names). The default tooltip for a list item is: "{{{set fieldname@tiddlername=itemvalue}}}". Note: if all list entries are single-line (i.e., you are not defining ANY custom tooltips), you can omit the horizontal rule between entries... each line of text will be treated as a separate list entry.
*''allowEdit'' //(for use with +~TiddlerName or *~TiddlerName param only)//<br>adds optional "edit list..." item to the end of the list, to enable quick editing of a tiddler-based list definition. Note: if the ''+~TiddlerName'' parameter refers to a tiddler that does not yet exist, the "edit list..." item is automatically added to the list, even if ''allowEdit'' was not specified. This allows you to place an 'empty' tiddler-based list into your content (e.g., """<<select fieldname =NewTiddlerName>>"""), and then create and define the tiddler-based list later on.
*''rows:nn''<br>specifies the number of lines to display in the list. If rows=1, a 'droplist' is displayed. If rows>1 a fixed-height listbox is used. By default (or if rows=0 is used), the listbox is displayed with enough lines to show all items without scrolling (i.e., "fit to contents - vertically")
*''width:xxx''<br>specifies the width of the list, using a CSS dimension value (px, em, in, cm, or %). The default is auto (i.e., "fit to contents - horizontally").
*''autoSave''<br>when used in EditTemplate, this keyword forces selection changes to be applied immediately rather than waiting for the "done" command to be invoked. Note: because the standard ViewTemplate toolbar does not have a "done" command to signal the end of the editing activity, ''autoSave'' is always enabled when working with a selection list that is being displayed in 'view mode'.
*''allowBlank''<br>when the value of a tiddler field is "undefined", a 'blank' item is added at the beginning of the list to represent the undefined field value. When a field value is subsequently selected, the blank item is removed from the list. Use the ''allowBlank'' keyword to always include the blank item in the list. Selecting the blank item sets the field value back to "undefined" (i.e., deletes the field).
*''allowOther''<br>when the value of a tiddler field does not match any of the values in the list, a special 'other' item is added at the end of the list so that the unrecognized field value can be shown. If another field value is subsequently selected, the 'other' item is removed from the list. Use the ''allowOther'' keyword to always include the 'other item in the list. When this item is selected, you will be prompted to enter a custom value to assign to the field.
*''allowMultiple''<br>when used with a listbox (e.g, rows>1), permits selection of multiple items using ctrl-click and shift-click. Selected values are stored in the tiddler field as a space-separated list, with brackets ({{{[[...]]}}}}) used as needed around values containing spaces. //note: multiple selection is not supported by droplists (rows=1)//
<<<
!!!!!Examples
<<<
''inline list definition:''
{{{<<select thing rows:1 eenie meenie miney moe>>}}}
<<select thing rows:1 eenie meenie miney moe>>
{{{<<select size rows:1 xsmall=30 small=32 medium=34 large=36 xlarge=38>>}}}
<<select size rows:1 xsmall=30 small=32 medium=34 large=36 xlarge=38>>
{{{<<select size allowOther xsmall=30 small=32 medium=34 large=36 xlarge=38>>}}}
<<select size allowOther xsmall=30 small=32 medium=34 large=36 xlarge=38>>
{{{<<select gender Male Female>>}}}
<<select gender Male Female>>
''tiddler-based list definition:''
{{{<<select color rows:1 +ListboxSample>>}}}
<<select color rows:1 +ListboxSample>>
{{{<<select color allowBlank allowOther allowMultiple +ListboxSample allowEdit>>}}}
<<select color allowBlank allowOther allowMultiple +ListboxSample allowEdit>>
{{{<<select demo@ListboxDemoTarget +ListboxNewSample>>}}}
<<select demo@ListboxDemoTarget +ListboxNewSample>>
''tag-based list definition:''
{{{<<select plugins rows:1 =systemConfig>>}}}
<<select plugins rows:1 allowBlank =systemConfig>>
{{{<<select samples rows:1 allowBlank =sample>>}}}
<<select samples rows:1 =sample>>
<<<
!!!!!Revisions
<<<
2009.06.15 [1.2.3] in setFieldValue(), eliminate extra tiddly brackets around single value selections
2009.06.15 [1.2.2] fixed infinite loop problem in refresh()
2009.06.15 [1.2.1] if not allowMultiple, handle field values containing space-separated lists as single values
2009.05.31 [1.2.0] added allowMultiple flag. Rewrote handler to allow option params in any order. Corrected handling of blank/other values.
2008.07.22 [1.1.0] added "=cookiename" syntax for storing selected value in cookie instead of a tiddler field
2008.04.28 [1.0.1] added "=tagvalue" syntax for generating lists of tiddlers tagged with a given value
2007.08.31 [0.8.2] corrected handling for "@tiddlername" syntax for non-default 'target' tiddler.
2007.08.06 [0.8.1] added support for "@here" keyword syntax and cleaned up handling for identifying 'target' tiddler. Also added 'onclick' handler for "other:" item, so that prompt dialog is presented even if "other" was already selected (and hence, no "onchange" event)
2007.07.29 [0.8.0] added getWikifiedData() and use of "*" prefix on TiddlerName so macros or inline scripts embedded in listbox definitions can generate dynamic lists based on current document content.
2007.07.26 [0.7.3] fixed call to config.macros.select.setFieldValue()
2007.07.24 [0.7.2] in setFieldValue(), 'touch' target tiddler AFTER setting value to avoid early refresh event that steps on listbox attributes, causing a fatal error (in IE only).
2007.06.28 [0.7.1] in render(), retrieve current val from tiddler editor control (when editing) or use stored field (when viewing).
2007.05.29 [0.7.0] split render() logic from handler(), added refresh() notification to auto sync lists that use +TiddlerName definition
2007.05.15 [0.6.1] code/documentation cleanup
2007.05.14 [0.6.0] lots more options
2007.05.12 [0.5.0] started
<<<
/***
|''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);
}
//}}}
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
/*********************************************************/
/*deleteCascade command for EditRecordToolbar*/
/********************************************************/
config.commands.deleteTiddlerCascade = {
hideReadOnly: true,
text: "deleteCascade",
tooltip: "Delete this tiddler and its children",
warning: "Deleting this tiddler will delete all the tiddlers directly dependent on this tiddler. Are you sure you want to delete '%0'?"
};
config.commands.deleteTiddlerCascade.handler = function (event, src, title) {
var children = store.getTiddlers();
if (children.length > 0){
for(var i=0;i<children.length;i++){
if(children[i].fields && children[i].fields.parent == title ) config.commands.deleteTiddlerCascade.handler(event, src, children[i].title);
}
}
var deleteIt = true;
if (config.options.chkConfirmDelete) {
deleteIt = confirm(this.warning.format([title]));
}
if (deleteIt) {
store.removeTiddler(title);
story.closeTiddler(title, true);
var EditTemplate=title+"EditTemplate";
if(config.shadowTiddlers[EditTemplate]!=null) config.shadowTiddlers[EditTemplate]=null;
var ViewTemplate=title+"ViewTemplate";
if(config.shadowTiddlers[ViewTemplate]!=null) config.shadowTiddlers[ViewTemplate]=null;
autoSaveChanges();
}
return false;
}
/*********************************************************
saveCascade command for EditRecordToolbar
********************************************************/
config.commands.saveTiddlerCascade = {
hideReadOnly: true,
text: "saveCascade",
tooltip: "Save this tiddler and cascade changes"
};
config.commands.saveTiddlerCascade.handler = function(event,src,title)
{
var newTitle = story.saveTiddler(title,event.shiftKey);
if(newTitle && newTitle != title){
var children = store.getTaggedTiddlers(title);
if(children.length > 0){
for(var i=0; i<children.length; i++){
window.shavinder.replace(children[i].tags, title, newTitle);
if(children[i].fields.parent == title) children[i].fields.parent = newTitle;
}
}
}
story.refreshAllTiddlers();
if(newTitle)
story.displayTiddler(null,newTitle);
return false;
};
/***************************************
**New Namespace**
This namespace shall contain some miscellaneous functions
******************************************/
if (!window.shavinder) window.shavinder = {};
//replace a value in an array with another
window.shavinder.replace = function(arrayName, replaceTo, replaceWith){
for(var i=0; i<arrayName.length; i++){
if(arrayName[i] == replaceTo){
arrayName.splice(i, 1, replaceWith);
}
}
};
//check is a value exists in an array
// Returns true if the passed value is found in the array. Returns false if it is not.
Array.prototype.inArray = function (value,caseSensitive){
var i;
for (i=0; i < this.length; i++) {
// use === to check for Matches. ie., identical (===),
if(caseSensitive){ //performs match even the string is case sensitive
if (this[i].toLowerCase() == value.toLowerCase()) {
return true;
}
}else{
if (this[i] == value) {
return true;
}
}
}
return false;
};
/**************************************
custom macro: showParentTag
************************************/
config.macros.showParent = {
label: "Parent: ",
tooltip: "Name of the Parent tiddler"
}
config.macros.showParent.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
if(tiddler instanceof Tiddler) {
var parent = "None";
parent = tiddler.fields.parent;
str = "Parent:[["+parent+"]]";
wikify(str, place);
}
/*****
var tags = story.findContainingTiddler(place).getAttribute("tags");
var fields=story.findContainingTiddler(place),getAttribute("fields").readBracketedList();
var parent = "None";
var prefix = "parent:"
parent = fields[parent]
if (tags.indexOf(prefix) != -1) parent = tags.substring( tags.indexOf(prefix)+prefix.length, tags.indexOf(" ",tags.indexOf(prefix)));
var inrHtml = "Parent: [[" + parent + "]]";
wikify(inrHtml, place);
****/
}
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<!--
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
-->
</div>
<div id='topMenu' refresh='content' tiddler='TopMenu'></div>
<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
}}}-->
/***
|''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"
});
*/
//}}}
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro="tiddler MoveTiddlerToTop'></span>
<span macro="tiddler ScrollToTop'></span>
<div class='toolbar border' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<h1>Qualification</h1>
<div class='viewer' >
<div macro='tiddler ShowParent'></div>
<table class='editRecord'>
<tr><td>Type:</td><td style="text-align:left;"><span macro='select qualification_type rows:1 +QualificationTypes'></span></td>
<td>Name:</td><td style="text-align:left;"><span macro='select qualification_name rows:1 +QualificationNames'></span> </td>
</tr><tr>
<td>Institution:</td><td><span macro='edit institution'></span></td>
<td>Board/Uni:</td><td><span macro='edit board-univ'></span></td>
</tr><tr>
<td>Year:</td><td><span macro='edit year'></span></td>
<td>Roll No:</td><td><span macro='edit rollno'></span></td>
</tr><tr>
<td>Obt Marks:</td><td><span macro='edit obt_marks'></span></td>
<td>Max Marks:</td><td><span macro='edit max_marks'></span></td>
</tr><tr>
<td>Grade:</td><td><span macro='edit grade'></span></td>
<td>Credits:</td><td><span macro='edit credits'></span></td>
</tr><tr>
<td>Division:</td><td style="text-align:left;"><span macro='select division rows:1 "I" "II" "III" '></span></td>
<td>Medium of Instruction:</td><td style="text-align:left;"><span macro='select medium rows:1 allowOther "English" "Hindi" "Punjabi" ' ></span></td>
</tr><tr>
<td> Result:</td><td><span macro='edit result'></span></td>
<td></td>
</tr>
</table>
<div style="display:none;" class='editor' macro='edit tags'></div>
</div>
<!--}}}-->
B.A.
B.Sc.
B.Com.
M.A.
M.Sc.
M.Com.
M.Phil.
Ph.D.
Degree
Diploma
Certificate
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro="tiddler MoveTiddlerToTop'></span>
<span macro="tiddler ScrollToTop'></span>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
</div>
<div class='title' macro='view title'>Qualification Id:</div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer'>
<div macro='tiddler ShowParent'></div>
<table class='viewRecord'>
<tr><td class='alignR'>Type:</td><td class='alignL'><span macro='view qualification_type'></span></td>
<td class='alignR'>Name:</td><td class='alignL'><span macro='view qualification_name'></span> </td>
</tr><tr>
<td class='alignR'>Institution:</td><td class='alignL'><span macro='view institution'></span></td>
<td class='alignR'>Board/Uni:</td><td class='alignL'><span macro='view board-univ'></span></td>
</tr><tr>
<td class='alignR'>Year:</td><td class='alignL'><span macro='view year'></span></td>
<td class='alignR'>Roll No:</td><td class='alignL'><span macro='view rollno'></span></td>
</tr><tr>
<td class='alignR'>Obt Marks:</td><td class='alignL'><span macro='view obt_marks'></span></td>
<td class='alignR'>Max Marks:</td><td class='alignL'><span macro='view max_marks'></span></td>
</tr><tr>
<td class='alignR'>Grade:</td><td class='alignL'><span macro='view grade'></span></td>
<td class='alignR'>Credits:</td><td class='alignL'><span macro='view credits'></span></td>
</tr><tr>
<td class='alignR'>Division:</td><td class='alignL'><span macro='view division'></span></td>
<td class='alignR'>Medium of Instruction:</td><td class='alignL'><span macro='view medium' ></span></td>
</tr><tr>
<td class='alignR'> Result:</td><td class='alignL'><span macro='view result'></span></td>
<td></td>
</tr>
</table>
</div>
<!--}}}-->
/***
|Name|RecentChangesPlugin|
|Source|http://www.TiddlyTools.com/#RecentChangesPlugin|
|Version|2.2.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|display droplist of recently changed tiddlers with goto, edit, and preview buttons|
!!!!!Usage
<<<
The {{{<<recentChanges>>}}} macro displays a droplist of all tiddlers that have been changed within the last N days (default=10 days).
{{{
<<recentChanges>>
<<recentChanges #ofdays summary noEdit previewheight previewclass>>
}}}
where:
* #ofdays specifies the time limit for listing changed tiddlers. Use 0 (zero) to list all tiddlers in the document.
* ''summary'' is an optional keyword that outputs only the summary text (without the droplist or buttons)
* ''noEdit'' is an optional keyword that hides the 'edit' button
* previewheight is a CSS height measurement and sets the FIXED height of the tiddler preview area (default is 15em)
* previewclass is any CSS classname, and can be used to apply custom styles to the preview area (default is to use the standard 'viewer' class)
<<<
!!!!!Examples
<<<
{{smallform{
{{{<<recentChanges>>}}}
<<recentChanges>>
{{{<<recentChanges 30 summary>>}}}
<<recentChanges 30 summary>>
{{{<<recentChanges 30 noedit 10em groupbox>>}}}
<<recentChanges 30 noedit 10em groupbox>>
}}}
<<<
!!!!!Revisions
<<<
2009.07.02 [2.2.0] added optional 'noedit' keyword to hide 'edit' button
2008.07.01 [2.1.0] added optional 'summary' keyword for simple text output
2008.05.01 [2.0.1] fixup for titles with double-quotes
2007.07.26 [2.0.0] re-written as plugin
2006.10.02 [1.0.0] initial release (as inline script ShowRecentChanges)
<<<
!!!!!Code
***/
//{{{
version.extensions.RecentChangesPlugin= {major: 2, minor: 2, revision: 0, date: new Date(2009,7,2)};
config.shadowTiddlers.RecentChanges='<recentChanges>>';
config.macros.recentChanges = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var days=10; if (!isNaN(params[0])) days=parseInt(params[0]); // time limit in days (use 0 for all tiddlers)
var summary=params[1]&¶ms[1].toLowerCase()=='summary'; if (summary) params.shift();
var noedit=params[1]&¶ms[1].toLowerCase()=='noedit'; if (noedit) params.shift();
var height='15em'; if (params[1]) height=params[1]; // preview area fixed height
var previewclass='viewer'; if (params[2]) previewclass=params[2]; // preview area CSS class
var tiddlers=store.getTiddlers('modified','excludeLists').reverse();
var count=tiddlers.length;
if (days) {
var timelimit=(new Date()).getTime()-86400000*days;
for (var count=0; count<tiddlers.length && tiddlers[count].modified>timelimit; count++);
}
var s=count+' tiddlers have changed since ';
s+=new Date(timelimit).formatString('DDD, MMM DDth YYYY 0hh:0mm');
s+=' ('+days+' days ago)';
if (summary)
{ wikify(s,place); return; }
var opts='<option value="">'+s+'</option>';
for (var i=0; i<count; i++) { var t=tiddlers[i];
opts+='<option value="'+t.title.replace(/"/g,""")+'">';
opts+=t.modified.formatString('YYYY.0MM.0DD 0hh:0mm')+' - '+t.title;
opts+='</option>';
}
var h=store.getTiddlerText('RecentChangesPlugin##html')
h=h.replace(/%options%/,opts);
h=h.replace(/%listwidth%/,noedit?79.5:69.5);
h=h.replace(/%noedit%/,noedit?'none':'inline');
createTiddlyElement(place,'div').innerHTML=h;
var preview=createTiddlyElement(place,'div',null,previewclass);
preview.style.display='none';
preview.style.whiteSpace='normal';
preview.style.overflow='auto';
preview.style.height=height;
}
}
//}}}
/***
//{{{
!html
<form><select size=1 name="list" style="width:%listwidth%%"
onchange="this.form.goto.disabled=this.form.edit.disabled=this.form.preview.disabled=!this.value.length;
var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
if (!this.value.length)
{ target.style.display='none'; this.form.preview.value='preview'; }
else if (target.style.display=='block') {
wikify('<'+'<tiddler [['+this.value+']]>'+'>',target);
target.style.display='block';
this.form.preview.value='done';
}
">%options%</select><!--
--><input type="button" name="goto" value="goto" disabled title="view selected tiddler" style="width:10%"
onclick="var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
target.style.display='none'; this.form.preview.value='preview';
story.displayTiddler(story.findContainingTiddler(this),this.form.list.value);
"><input type="button" name="edit" value="edit" disabled title="edit selected tiddler" style="width:10%;display:%noedit%"
onclick="var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
target.style.display='none'; this.form.preview.value='preview';
story.displayTiddler(story.findContainingTiddler(this),this.form.list.value,DEFAULT_EDIT_TEMPLATE);
"><input type="button" name="preview" value="preview" disabled title="show/hide tiddler preview" style="width:10%"
onclick="var target=this.parentNode.parentNode.nextSibling;
if (this.value=='preview') {
removeChildren(target);
wikify('<'+'<tiddler [['+this.form.list.value+']]>'+'>',target);
target.style.display=this.form.list.value.length?'block':'none'; this.value='done';
} else {
removeChildren(target);
target.style.display='none'; this.value='preview';
}
"></form>
!end
//}}}
***/
/%
|Name|RefreshPageDisplay|
|Source|http://www.TiddlyTools.com/#RefreshPageDisplay|
|Version|1.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|Refresh all tiddlers and page elements without restarting|
%/<script label="$1" title="Redisplay current page content WITHOUT RESTARTING!">
story.forEachTiddler(function(t,e){story.refreshTiddler(t,null,true)});
refreshDisplay();
return false;
</script><script>
if ("$1"=="$"+"1") place.lastChild.innerHTML="refresh page display";
</script>
/%
|Name|RefreshTiddler|
|Source|http://www.TiddlyTools.com/#RefreshTiddler|
|Version|0.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|link that forces a refresh of the current tiddler|
usage: <<tiddler RefreshTiddler with: "label" "tooltip">>
where label and tooltip are optional and default to "refresh" and "redisplay tiddler content", respectively.
%/<script label="refresh" title="redisplay tiddler content">
var here=story.findContainingTiddler(place); if (!here) return false;
story.refreshTiddler(here.getAttribute("tiddler"),null,true);
return false;
</script><script>
if ("$1"!="$"+"1") place.lastChild.innerHTML="$1";
if ("$2"!="$"+"2") place.lastChild.title="$2";
</script>
/***
|Name|SearchOptionsPlugin|
|Source|http://www.TiddlyTools.com/#SearchOptionsPlugin|
|Documentation|http://www.TiddlyTools.com/#SearchOptionsPluginInfo|
|Version|3.0.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.search, TiddlyWiki.prototype.search, config.macros.search.onKeyPress|
|Options|##Configuration|
|Description|extend core search function with additional user-configurable options|
Adds extra options to core search function including selecting which data items to search, enabling/disabling incremental key-by-key searches, and generating a ''list of matching tiddlers'' instead of immediately displaying all matches. This plugin also adds syntax for rendering 'search links' within tiddler content to embed one-click searches using pre-defined 'hard-coded' search terms.
!!!!!Documentation
>see [[SearchOptionsPluginInfo]]
!!!!!Configuration
<<<
Search in:
<<option chkSearchTitles>> titles <<option chkSearchText>> text <<option chkSearchTags>> tags <<option chkSearchFields>> fields <<option chkSearchShadows>> shadows
<<option chkSearchHighlight>> Highlight matching text in displayed tiddlers
<<option chkSearchList>> Show list of matches
<<option chkSearchListTiddler>> Write list to [[SearchResults]] tiddler
<<option chkSearchTitlesFirst>> Show title matches first
<<option chkSearchByDate>> Sort matching tiddlers by modification date (most recent first)
<<option chkIncrementalSearch>> Incremental key-by-key search: {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters, {{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay
<<option chkSearchOpenTiddlers>> Search only in tiddlers that are currently displayed
<<option chkSearchExcludeTags>> Exclude tiddlers tagged with: <<option txtSearchExcludeTags>>
<<<
!!!!!Revisions
<<<
2009.01.16 [3.0.5] added chkSearchOpenTiddlers option to limit searches to displayed tiddlers only
|please see [[SearchOptionsPluginInfo]] for additional revision details|
2005.10.18 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.SearchOptionsPlugin= {major: 3, minor: 0, revision: 5, date: new Date(2009,1,16)};
var co=config.options; // abbrev
if (co.chkSearchTitles===undefined) co.chkSearchTitles=true;
if (co.chkSearchText===undefined) co.chkSearchText=true;
if (co.chkSearchTags===undefined) co.chkSearchTags=true;
if (co.chkSearchFields===undefined) co.chkSearchFields=true;
if (co.chkSearchTitlesFirst===undefined) co.chkSearchTitlesFirst=true;
if (co.chkSearchList===undefined) co.chkSearchList=true;
if (co.chkSearchHighlight===undefined) co.chkSearchHighlight=true;
if (co.chkSearchListTiddler===undefined) co.chkSearchListTiddler=false;
if (co.chkSearchByDate===undefined) co.chkSearchByDate=false;
if (co.chkIncrementalSearch===undefined) co.chkIncrementalSearch=true;
if (co.chkSearchShadows===undefined) co.chkSearchShadows=true;
if (co.txtIncrementalSearchDelay===undefined) co.txtIncrementalSearchDelay=500;
if (co.txtIncrementalSearchMin===undefined) co.txtIncrementalSearchMin=3;
if (co.chkSearchOpenTiddlers===undefined) co.chkSearchOpenTiddlers=false;
if (co.chkSearchExcludeTags===undefined) co.chkSearchExcludeTags=true;
if (co.txtSearchExcludeTags===undefined) co.txtSearchExcludeTags="excludeSearch";
if (config.macros.search.reportTitle==undefined)
config.macros.search.reportTitle="SearchResults"; // note: not a cookie!
config.macros.search.label+="\xa0"; // a little bit of space just because it looks better
//}}}
// // searchLink: {{{[search[text to find]] OR [search[text to display|text to find]]}}}
//{{{
config.formatters.push( {
name: "searchLink",
match: "\\[search\\[",
lookaheadRegExp: /\[search\[(.*?)(?:\|(.*?))?\]\]/mg,
prompt: "search for: '%0'",
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var label=lookaheadMatch[1];
var text=lookaheadMatch[2]||label;
var prompt=this.prompt.format([text]);
var btn=createTiddlyButton(w.output,label,prompt,
function(){story.search(this.getAttribute("searchText"))},"searchLink");
btn.setAttribute("searchText",text);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
});
//}}}
// // incremental search uses option settings instead of hard-coded delay and minimum input values
//{{{
var fn=config.macros.search.onKeyPress;
fn=fn.toString().replace(/500/g, "config.options.txtIncrementalSearchDelay||500");
fn=fn.toString().replace(/> 2/g, ">=(config.options.txtIncrementalSearchMin||3)");
eval("config.macros.search.onKeyPress="+fn);
//}}}
// // REPLACE story.search() for option to "show search results in a list"
//{{{
Story.prototype.search = function(text,useCaseSensitive,useRegExp)
{
var co=config.options; // abbrev
var re=new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
if (config.options.chkSearchHighlight) highlightHack=re;
var matches = store.search(re,co.chkSearchByDate?"modified":"title","");
if (co.chkSearchByDate) matches=matches.reverse(); // most recent first
var q = useRegExp ? "/" : "'";
clearMessage();
if (!matches.length) {
if (co.chkSearchListTiddler) discardSearchResults();
displayMessage(config.macros.search.failureMsg.format([q+text+q]));
} else {
if (co.chkSearchList||co.chkSearchListTiddler)
reportSearchResults(text,matches);
else {
var titles = []; for(var t=0; t<matches.length; t++) titles.push(matches[t].title);
this.closeAllTiddlers(); story.displayTiddlers(null,titles);
displayMessage(config.macros.search.successMsg.format([matches.length, q+text+q]));
}
}
highlightHack = null;
}
//}}}
// // REPLACE store.search() for enhanced searching/sorting options
//{{{
TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
{
var co=config.options; // abbrev
var tids = this.reverseLookup("tags",excludeTag,false,sortField);
var opened=[]; story.forEachTiddler(function(tid,elem){opened.push(tid);});
// eliminate tiddlers tagged with excluded tags
if (co.chkSearchExcludeTags&&co.txtSearchExcludeTags.length) {
var ex=co.txtSearchExcludeTags.readBracketedList();
var temp=[]; for(var t=tids.length-1; t>=0; t--)
if (!tids[t].tags.containsAny(ex)) temp.push(tids[t]);
tids=temp;
}
// scan for matching titles first...
var results = [];
if (co.chkSearchTitles) {
for(var t=0; t<tids.length; t++) {
if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue;
if(tids[t].title.search(searchRegExp)!=-1) results.push(tids[t]);
}
if (co.chkSearchShadows)
for (var t in config.shadowTiddlers) {
if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue;
if ((t.search(searchRegExp)!=-1) && !store.tiddlerExists(t))
results.push((new Tiddler()).assign(t,config.shadowTiddlers[t]));
}
}
// then scan for matching text, tags, or field data
for(var t=0; t<tids.length; t++) {
if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue;
if (co.chkSearchText && tids[t].text.search(searchRegExp)!=-1)
results.pushUnique(tids[t]);
if (co.chkSearchTags && tids[t].tags.join(" ").search(searchRegExp)!=-1)
results.pushUnique(tids[t]);
if (co.chkSearchFields && store.forEachField!=undefined)
store.forEachField(tids[t],
function(tid,field,val) {
if (val.search(searchRegExp)!=-1) results.pushUnique(tids[t]);
},
true); // extended fields only
}
// then check for matching text in shadows
if (co.chkSearchShadows)
for (var t in config.shadowTiddlers) {
if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue;
if ((config.shadowTiddlers[t].search(searchRegExp)!=-1) && !store.tiddlerExists(t))
results.pushUnique((new Tiddler()).assign(t,config.shadowTiddlers[t]));
}
// if not 'titles first', or sorting by modification date,
// re-sort results to so titles, text, tag and field matches are mixed together
if(!sortField) sortField = "title";
var bySortField=function(a,b){
if(a[sortField]==b[sortField])return(0);else return(a[sortField]<b[sortField])?-1:+1;
}
if (!co.chkSearchTitlesFirst || co.chkSearchByDate) results.sort(bySortField);
return results;
}
//}}}
// // HIJACK core {{{<<search>>}}} macro to add "report" and "simple inline" output
//{{{
config.macros.search.SOP_handler=config.macros.search.handler;
config.macros.search.handler = function(place,macroName,params)
{
// if "report", use SearchOptionsPlugin report generator for inline output
if (params[1]&¶ms[1].substr(0,6)=="report") {
var keyword=params[0];
var options=params[1].split("=")[1]; // split "report=option+option+..."
var heading=params[2]?params[2].unescapeLineBreaks():"";
var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
if (matches.length) wikify(heading+window.formatSearchResults(keyword,matches,options),place);
} else if (params[1]) {
var keyword=params[0];
var heading=params[1]?params[1].unescapeLineBreaks():"";
var seperator=params[2]?params[2].unescapeLineBreaks():", ";
var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
if (matches.length) {
var out=[];
for (var m=0; m<matches.length; m++) out.push("[["+matches[m].title+"]]");
wikify(heading+out.join(seperator),place);
}
} else
config.macros.search.SOP_handler.apply(this,arguments);
};
//}}}
// // SearchResults panel handling
//{{{
setStylesheet(".searchResults { padding:1em 1em 0 1em; }","searchResults"); // matches std tiddler padding
config.macros.search.createPanel=function(text,matches,body) {
function getByClass(e,c) { var d=e.getElementsByTagName("div");
for (var i=0;i<d.length;i++) if (hasClass(d[i],c)) return d[i]; }
var panel=createTiddlyElement(null,"div","searchPanel","searchPanel");
this.renderPanel(panel,text,matches,body);
var oldpanel=document.getElementById("searchPanel");
if (!oldpanel) { // insert new panel just above tiddlers
var da=document.getElementById("displayArea");
da.insertBefore(panel,da.firstChild);
} else { // if panel exists
var oldwrap=getByClass(oldpanel,"searchResults");
var newwrap=getByClass(panel,"searchResults");
// if no prior content, just insert new content
if (!oldwrap) oldpanel.insertBefore(newwrap,null);
else { // swap search results content but leave containing panel intact
oldwrap.style.display='block'; // unfold wrapper if needed
var i=oldwrap.getElementsByTagName("input")[0]; // get input field
if (i) { var pos=this.getCursorPos(i); i.onblur=null; } // get cursor pos, ignore blur
oldpanel.replaceChild(newwrap,oldwrap);
panel=oldpanel; // use existing panel
}
}
this.showPanel(true,pos);
return panel;
}
config.macros.search.renderPanel=function(panel,text,matches,body) {
var wrap=createTiddlyElement(panel,"div",null,"searchResults");
wrap.onmouseover = function(e){ addClass(this,"selected"); }
wrap.onmouseout = function(e){ removeClass(this,"selected"); }
// create toolbar: "open all", "fold/unfold", "close"
var tb=createTiddlyElement(wrap,"div",null,"toolbar");
var b=createTiddlyButton(tb, "open all", "open all matching tiddlers", function() {
story.displayTiddlers(null,this.getAttribute("list").readBracketedList()); return false; },"button");
var list=""; for(var t=0;t<matches.length;t++) list+='[['+matches[t].title+']] ';
b.setAttribute("list",list);
var b=createTiddlyButton(tb, "fold", "toggle display of search results", function() {
config.macros.search.foldPanel(this); return false; },"button");
var b=createTiddlyButton(tb, "close", "dismiss search results", function() {
config.macros.search.showPanel(false); return false; },"button");
createTiddlyText(createTiddlyElement(wrap,"div",null,"title"),"Search for: "+text); // title
wikify(body,createTiddlyElement(wrap,"div",null,"viewer")); // report
return panel;
}
config.macros.search.showPanel=function(show,pos) {
var panel=document.getElementById("searchPanel");
var i=panel.getElementsByTagName("input")[0];
i.onfocus=show?function(){config.macros.search.stayFocused(true);}:null;
i.onblur=show?function(){config.macros.search.stayFocused(false);}:null;
if (show && panel.style.display=="block") { // if shown, grab focus, restore cursor
if (i&&this.stayFocused()) { i.focus(); this.setCursorPos(i,pos); }
return;
}
if(!config.options.chkAnimate) {
panel.style.display=show?"block":"none";
if (!show) { removeChildren(panel); config.macros.search.stayFocused(false); }
} else {
var s=new Slider(panel,show,false,show?"none":"children");
s.callback=function(e,p){e.style.overflow="visible";}
anim.startAnimating(s);
}
return panel;
}
config.macros.search.foldPanel=function(button) {
var d=document.getElementById("searchPanel").getElementsByTagName("div");
for (var i=0;i<d.length;i++) if (hasClass(d[i],"viewer")) var v=d[i]; if (!v) return;
var show=v.style.display=="none";
if(!config.options.chkAnimate)
v.style.display=show?"block":"none";
else {
var s=new Slider(v,show,false,"none");
s.callback=function(e,p){e.style.overflow="visible";}
anim.startAnimating(s);
}
button.innerHTML=show?"fold":"unfold";
return false;
}
config.macros.search.stayFocused=function(keep) { // TRUE/FALSE=set value, no args=get value
if (keep===undefined) return this.keepReportInFocus;
this.keepReportInFocus=keep;
return keep
}
config.macros.search.getCursorPos=function(i) {
var s=0; var e=0; if (!i) return { start:s, end:e };
try {
if (i.setSelectionRange) // FF
{ s=i.selectionStart; e=i.selectionEnd; }
if (document.selection && document.selection.createRange) { // IE
var r=document.selection.createRange().duplicate();
var len=r.text.length; s=0-r.moveStart('character',-100000); e=s+len;
}
}catch(e){};
return { start:s, end:e };
}
config.macros.search.setCursorPos=function(i,pos) {
if (!i||!pos) return; var s=pos.start; var e=pos.end;
if (i.setSelectionRange) //FF
i.setSelectionRange(s,e);
if (i.createTextRange) // IE
{ var r=i.createTextRange(); r.collapse(true); r.moveStart("character",s); r.select(); }
}
//}}}
// // SearchResults report generation
// note: these functions are defined globally, so they can be more easily redefined to customize report formats//
//{{{
if (!window.reportSearchResults) window.reportSearchResults=function(text,matches)
{
var cms=config.macros.search; // abbrev
var body=window.formatSearchResults(text,matches);
if (!config.options.chkSearchListTiddler) // show #searchResults panel
window.scrollTo(0,ensureVisible(cms.createPanel(text,matches,body)));
else { // write [[SearchResults]] tiddler
var title=cms.reportTitle;
var who=config.options.txtUserName;
var when=new Date();
var tags="excludeLists excludeSearch temporary";
var tid=store.getTiddler(title); if (!tid) tid=new Tiddler();
tid.set(title,body,who,when,tags);
store.addTiddler(tid);
story.closeTiddler(title);
story.displayTiddler(null,title);
}
}
if (!window.formatSearchResults) window.formatSearchResults=function(text,matches,opt)
{
var body='';
var title=config.macros.search.reportTitle
var q = config.options.chkRegExpSearch ? "/" : "'";
if (!opt) var opt="all";
var parts=opt.split("+");
for (var i=0; i<parts.length; i++) { var p=parts[i].toLowerCase();
if (p=="again"||p=="all") body+=window.formatSearchResults_again(text,matches);
if (p=="summary"||p=="all") body+=window.formatSearchResults_summary(text,matches);
if (p=="list"||p=="all") body+=window.formatSearchResults_list(text,matches);
if (p=="buttons"||p=="all") body+=window.formatSearchResults_buttons(text,matches);
}
return body;
}
if (!window.formatSearchResults_again) window.formatSearchResults_again=function(text,matches)
{
var title=config.macros.search.reportTitle
var body='';
// search again
body+='{{span{<<search "'+text.replace(/"/g,'"')+'">> /%\n';
body+='%/<html><input type="button" value="search again"';
body+=' onclick="var t=this.parentNode.parentNode.getElementsByTagName(\'input\')[0];';
body+=' config.macros.search.doSearch(t); return false;">';
body+=' <a href="javascript:;" onclick="';
body+=' var e=this.parentNode.nextSibling;';
body+=' var show=e.style.display!=\'block\';';
body+=' if(!config.options.chkAnimate) e.style.display=show?\'block\':\'none\';';
body+=' else anim.startAnimating(new Slider(e,show,false,\'none\'));';
body+=' return false;">options...</a>';
body+='</html>@@display:none;border-left:1px dotted;margin-left:1em;padding:0;padding-left:.5em;font-size:90%;/%\n';
body+=' %/<<option chkSearchTitles>>titles /%\n';
body+=' %/<<option chkSearchText>>text /%\n';
body+=' %/<<option chkSearchTags>>tags /%\n';
body+=' %/<<option chkSearchFields>>fields /%\n';
body+=' %/<<option chkSearchShadows>>shadows\n';
body+=' <<option chkCaseSensitiveSearch>>case-sensitive /%\n';
body+=' %/<<option chkRegExpSearch>>text patterns /%\n';
body+=' %/<<option chkSearchByDate>>sorted by date\n';
body+=' <<option chkSearchHighlight>> highlight matching text in displayed tiddlers\n';
body+=' <<option chkIncrementalSearch>>incremental key-by-key search: /%\n';
body+=' %/{{twochar{<<option txtIncrementalSearchMin>>}}} or more characters, /%\n';
body+=' %/{{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay\n';
body+=' <<option chkSearchOpenTiddlers>> search only in tiddlers that are currently displayed\n';
body+=' <<option chkSearchExcludeTags>>exclude tiddlers tagged with:\n';
body+=' {{editor{<<option txtSearchExcludeTags>>}}}/%\n';
body+='%/@@}}}\n\n';
return body;
}
if (!window.formatSearchResults_summary) window.formatSearchResults_summary=function(text,matches)
{
// summary: nn tiddlers found matching '...', options used
var body='';
var co=config.options; // abbrev
var title=config.macros.search.reportTitle
var q = co.chkRegExpSearch ? "/" : "'";
body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\n";
var opts=[];
if (co.chkSearchTitles) opts.push("titles");
if (co.chkSearchText) opts.push("text");
if (co.chkSearchTags) opts.push("tags");
if (co.chkSearchFields) opts.push("fields");
if (co.chkSearchShadows) opts.push("shadows");
if (co.chkSearchOpenTiddlers) body+="^^//search limited to displayed tiddlers only//^^\n";
body+="~~ searched in "+opts.join(" + ")+"~~\n";
body+=(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"^^ using ":"")
+(co.chkCaseSensitiveSearch?"case-sensitive ":"")
+(co.chkRegExpSearch?"pattern ":"")
+(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"matching^^\n":"");
return body;
}
if (!window.formatSearchResults_list) window.formatSearchResults_list=function(text,matches)
{
// bullet list of links to matching tiddlers
var body='';
var pattern=co.chkRegExpSearch?text:text.escapeRegExp();
var sensitive=co.chkCaseSensitiveSearch?"mg":"img";
var link='{{tiddlyLinkExisting{<html><nowiki><a href="javascript:;" onclick="'
+'if(config.options.chkSearchHighlight)'
+' highlightHack=new RegExp(\x27'+pattern+'\x27.escapeRegExp(),\x27'+sensitive+'\x27);'
+'story.displayTiddler(null,\x27%0\x27);'
+'highlightHack = null; return false;'
+'" title="%2">%1</a></html>}}}';
for(var t=0;t<matches.length;t++) {
body+="* ";
if (config.options.chkSearchByDate)
body+=matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" ";
var title=matches[t].title;
var fixup=title.replace(/'/g,"\\x27").replace(/"/g,"\\x22");
var tid=store.getTiddler(title);
var tip=tid?tid.getSubtitle():''; tip=tip.replace(/"/g,""");
body+=link.format([fixup,title,tip])+'\n';
}
return body;
}
if (!window.formatSearchResults_buttons) window.formatSearchResults_buttons=function(text,matches)
{
// embed buttons only if writing SearchResults to tiddler
if (!config.options.chkSearchListTiddler) return "";
// "open all" button
var title=config.macros.search.reportTitle;
var body="";
body+="@@diplay:block;<html><input type=\"button\" href=\"javascript:;\" "
+"onclick=\"story.displayTiddlers(null,[";
for(var t=0;t<matches.length;t++)
body+="'"+matches[t].title.replace(/\'/mg,"\\'")+"'"+((t<matches.length-1)?", ":"");
body+="],1);\" accesskey=\"O\" value=\"open all matching tiddlers\"></html> ";
// "discard SearchResults" button
body+="<html><input type=\"button\" href=\"javascript:;\" "
+"onclick=\"discardSearchResults()\" value=\"discard "+title+"\"></html>";
body+="@@\n";
return body;
}
if (!window.discardSearchResults) window.discardSearchResults=function()
{
// remove the tiddler
story.closeTiddler(config.macros.search.reportTitle);
store.deleteTiddler(config.macros.search.reportTitle);
store.notify(config.macros.search.reportTitle,true);
}
//}}}
/***
|Name|SearchOptionsPluginInfo|
|Source|http://www.TiddlyTools.com/#SearchOptionsPlugin|
|Documentation|http://www.TiddlyTools.com/#SearchOptionsPluginInfo|
|Version|3.0.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for SearchOptionsPlugin|
Extend core search function with additional user-configurable options including selecting which data items to search, enabling/disabling incremental key-by-key searches, and generating a ''list of matching tiddler'' instead of immediately displaying all matches. This plugin also adds syntax for rendering 'search links' within tiddler content to embed one-click searches using pre-defined 'hard-coded' search terms.
!!!!!Search link Syntax
<<<
To insert a 'search link' into tiddler content, you can write:
{{{
[search[text to find]]
}}}
or
{{{
[search[text to display|text to find]]
}}}
Clicking on the resulting search link will trigger the search functionality, just as if the specified 'text to find' had been entered into the standard search input field usually displayed in the document sidebar.
<<<
!!!!!Inline output: search macro syntax
<<<
Alternatively, to embed search results lists directly into your tiddler content, you can use:
{{{
<<search "text" report>> (report is a literal keyword)
<<search "text" "heading" "separator">> (simple inline generator)
}}}
<<<
!!!!!Inline output examples:
<<<
*+++*[<<search "wood">>]>...
<<search "wood">>
===
*+++*[<<search "wood" "/%%/">>]>...
<<search "wood" "/%%/">>
===
*+++*[<<search "wood" "See also: ">>]>...
<<search "wood" "See also: ">>
===
*+++*[<<search "wood" "See also:\n*" "\n*">>]>...
<<search "wood" "See also:\n*" "\n*">>
===
*+++*[<<search "wood" report=list "See also:">>]>...
<<search "wood" report=list "See Also:" >>
===
*+++*[<<search "wood" report>>]>...
<<search "wood" report>>
===
*+++*[<<search "wood" report=>>]>...
<<search "wood" report=>>
===
*+++*[<<search "wood" report=all>>]>...
<<search "wood" report=all>>
===
*+++*[<<search "wood" report=summary+buttons+again+list>>]>...
<<search "wood" report=summary+buttons+again+list>>
===
*+++*[<<search "wood" report=summary+again>>]>...
<<search "wood" report=summary+again>>
===
*+++*[<<search "wood" report=summary>>]>...
<<search "wood" report=summary>>
===
<<<
!!!!!Configuration
<<<
Search in:
<<option chkSearchTitles>> titles <<option chkSearchText>> text <<option chkSearchTags>> tags <<option chkSearchFields>> fields <<option chkSearchShadows>> shadows
{{{<<option chkSearchTitles>> <<option chkSearchText>> <<option chkSearchTags>>}}}
{{{<<option chkSearchFields>> <<option chkSearchShadows>>}}}
<<option chkSearchHighlight>> Highlight matching text in displayed tiddlers {{{<<option chkSearchHighlight>>}}}
<<option chkSearchList>> Show list of matches {{{<<option chkSearchList>>}}}
<<option chkSearchListTiddler>> Write list to [[SearchResults]] tiddler {{{<<option chkSearchListTiddler>>}}}
<<option chkSearchTitlesFirst>> Show title matches first {{{<<option chkSearchTitlesFirst>>}}}
<<option chkSearchByDate>> Sort matching tiddlers by date {{{<<option chkSearchByDate>>}}}
<<option chkIncrementalSearch>> Incremental key-by-key search: {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters, {{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay
{{{<<option chkSearchIncremental>> <<option txtSearchIncrementalMin>> <<option txtSearchIncrementalDelay>>}}}
<<option chkSearchOpenTiddlers>> Search only in tiddlers that are currently displayed {{{<<option chkSearchOpenTiddlers>>}}}
<<option chkSearchExcludeTags>> Exclude tiddlers tagged with: <<option txtSearchExcludeTags>>
{{{<<option chkSearchExcludeTags>>}}} {{{<<option txtSearchExcludeTags>>}}}
<<<
!!!!!Revisions
<<<
2009.01.16 [3.0.5] added chkSearchOpenTiddlers option to limit searches to displayed tiddlers only
2009.01.15 [3.0.4] in formatSearchResults_list(), corrected link generation to properly handle single-quotes and double-quotes in tiddler titles
2009.01.09 [3.0.3] added chkSearchHighlight to optionally disable highlighting of matched text
2009.01.05 [3.0.2] in formatSearchResults_list(), set/clear 'highlightHack' via HTML links so that search term will be highlighted when displaying tiddlers.
2008.10.14 [3.0.1] changed panel class from "tiddler" to "searchPanel" and added style definition for "searchPanel". Fixes ticket #771 (in IE, links from search results were reporting errors due to "fake" tiddler class wrapper)
2008.10.02 [3.0.0] added optional list of tags to use for excluding tiddler from searches (default="excludeLists").
2008.09.24 [2.9.9] performance improvment to reportSearchResults(): when rendering a real SearchResults tiddler, store.notify() isn't needed since the results tiddler is always explicitly closed and redrawn each time.
2008.09.20 [2.9.8] corrected createPanel() and renderPanel() so toolbar will be correctly shown/hidden on mouseover/mouseout.
2008.09.19 [2.9.7] fixes to panel handling for IE, Safari, and others. Changed panel id to #searchPanel and added .searchResults CSS class wrapper around panel content. Fixed fold/unfold handling.
2008.09.18 [2.9.6] refactored panel handling code, added 'fold/unfold' panel toolbar command, added dynamic 'title' (shows search term), added txtIncrementalSearchMin option
2008.09.17 [2.9.5] added focus and cursor handling for 'search again' field in #searchResults DIV report so that an incremental key-by-key search doesn't interfere with continuous typing into the field.
2008.09.17 [2.9.4] fix 'flicker' when updating #searchResults DIV by wikify()ing to an 'offscreen' DIV and then using replaceChild() instead of using removeChildren() followed by wikify()
2008.09.16 [2.9.3] changed report layout, added "search again" and collapsible 'options' section with incremental search checkbox and "txtIncrementalSearchDelay" timer tweak to onKeyPress()
2008.08.25 [2.9.2] added animation to search results DIV. Also, the #searchResults DOM element is only auto-created if it does not exist ... and when closed, the DIV is simply hidden rather than removed. This allows custom placement of search results report in the PageTemplate definition.
2008.08.23 [2.9.1] story column search results uses {{{<<moveablePanel>>}}}
2008.08.22 [2.9.0] default is now to show search results at top of story column, similar to FND's SimpleSearchPlugin display, with an option to generate SearchResults tiddler as before. Also changed 'chkSearchIncremental' to 'chkIncrementalSearch' to match core option variable
2008.08.12 [2.8.2] change default for chkSearchByDate back to FALSE, and adjusted "list" and "again" output formats (minor tweaks requested by PhilWhitehouse for use on TiddlyWiki.com)
2008.08.11 [2.8.1] changed defaults for chkSearchTitlesFirst, chkSearchList and chkSearchShadows to TRUE to enable enhanced search results output as soon as plugin is installed.
2008.06.21 [2.8.0] added extended syntax for {{{<<search "text" report heading>> and <<search "text" "heading" "seperator">>}}}
2008.05.03 [2.7.1] in searchLink formatter handler(), use separate setAttribute() call instead of passing attribs to createTiddlyButton(). Avoids conflict with errant code in TiddlerNotesPlugin (v2.1 26/10/07)
2008.04.29 [2.7.0] added searchLink formatter (syntax: {{{[search[text]]}}} or {{{[search[display|text]]}}})
2008.04.08 [2.6.2] don't automatically add options to AdvancedOptions shadow tiddler
2007.02.17 [2.6.1] added redefinition of config.macros.search.onKeyPress() to restore check to bypass key-by-key searching (i.e., when chkSearchIncremental==false), which had been unintentionally removed with v2.6.0
2007.02.13 [2.6.0] remove redefinition of config.macros.search.handler since core now includes handling for ENTER key.
2007.02.08 [2.5.1] include 'temporary' tag when creating SearchResults (for use with TemporaryTiddlersPlugin)
2007.01.29 [2.5.0] added support for "sort results by date". Default is to sort alphabetically (standard). When sorted by dates, most recent changes are shown first
2006.10.10 [2.4.0] added support for "search in tiddler data" (tiddler.fields) Default is to search extended data.
2006.04.06 [2.3.0] added support for "search in shadow tiddlers". Default is *not* to search in the shadows (i.e. standard TW behavior). Note: if a shadow tiddler has a 'real' counterpart, only the real tiddler is searched, since the shadow is inaccessible for viewing/editing.
2006.02.03 [2.2.1] rewrite timeout clearing code and blank search text handling to match 2.0.4 core release changes. note that core no longer permits "blank=all" searches, so neither does this plugin. To search for all, use "." with text patterns enabled.
2006.02.02 [2.2.0] in search.handler(), KeyHandler() function clears 'left over' timeout when search input is < 3 chars. Prevents searching on shorter text when shortened by rapid backspaces (<500msec)
2006.02.01 [2.1.9] in Story.prototype.search(), correct inverted logic for using/not using regular expressions when searching
also, blank search text now presents "No search text. Continue anyway?" confirm() message box, so search on blank can still be processed if desired by user.
2006.02.01 [2.1.8] in doSearch(), added alert/return if search text is blank
2006.01.20 [2.1.7] fixed setting of config.macros.search.reportTitle so that Tweaks can override it.
2006.01.19 [2.1.6] improved SearchResults formatting, added a "search again" form to the report (based on a suggestion from MorrisGray)
define results report title using config.macros.search.reportTitle instead of hard-coding the tiddler title
2006.01.18 [2.1.5] Created separate functions for reportSearchResults(text,matches) and discardSearchResults(), so that other developers can create alternative report generators.
2006.01.17 [2.1.4] Use regExp.search() instead of regExp.test() to scan for matches. Correctd the problem where only half the matching tiddlers (the odd-numbered ones) were being reported.
2006.01.15 [2.1.3] Added information (date/time, username, search options used) to SearchResults output
2006.01.10 [2.1.2] use displayTiddlers() to render matched tiddlers. This lets you display multiple matching tiddlers, even if SinglePageModePlugin is enabled.
2006.01.08 [2.1.1] corrected invalid variable reference, "txt.value" to "text" in story.search()
2006.01.08 [2.1.0] re-write to match new store.search(), store.search.handler() and story.search() functions.
2005.12.30 [2.0.0] Upgraded to TW2.0. When rendering SearchResults tiddler, closeTiddler() first to ensure display is refreshed.
2005.12.26 [1.4.0] added option to search for matching text in tiddler tags
2005.12.21 [1.3.7] use \\ to 'escape' single quotes in tiddler titles when generating "Open all matching tiddlers" link. Also, added access key: "O", to trigger "open all" link. Based on a suggestion by UdoBorkowski.
2005.12.18 [1.3.6] call displayMessage() AFTER showing matching tiddlers so message is not cleared too soon
2005.12.17 [1.3.5] if no matches found, just display message and delete any existing SearchResults tiddler.
2005.12.17 [1.3.4] use {/%%/{/%%/{ and }/%%/}/%%/} to 'escape' display text in SearchResults tiddler to ensure that formatting contained in search string is not rendered. Based on a suggestion by UdoBorkowski.
2005.12.14 [1.3.3] tag SearchResults tiddler with 'excludeSearch' so it won't list itself in subsequent searches. Based on a suggestion by UdoBorkowski.
2005.12.14 [1.3.2] added "open all matching tiddlers..." link to search results output. Based on a suggestion by UdoBorkowski.
2005.12.10 [1.3.1] added "discard search results" link to end of search list tiddler output for quick self-removal of 'SearchResults' tiddler.
2005.12.01 [1.3.0] added chkSearchIncremental to enable/disable 'incremental' searching (i.e., search after each keystroke) (default is ENABLED).
added handling for Enter key so it can be used to start a search. Based on a suggestion by LyallPearce
2005.11.25 [1.2.1] renamed from SearchTitleOrTextPlugin to SearchOptionsPlugin
2005.11.25 [1.2.0] added chkSearchList option. Based on a suggestion by RodneyGomes
2005.10.19 [1.1.0] added chkSearchTitlesFirst option. Based on a suggestion by ChristianHauck
2005.10.18 [1.0.0] Initial Release. Based on a suggestion by LyallPearce.
<<<
<script>
place.parentNode.previousSibling.firstChild.setAttribute('class','AttendanceInput');
place.parentNode.previousSibling.firstChild.setAttribute('maxLength','1');
</script>
@@display:block;text-align:center;shavinderpalsingh@gmail.com@@
<script>
var here=story.findContainingTiddler(place);
if(here==null) return false;
var classTiddler=store.getTiddler(here.getAttribute('tiddler'));
if(classTiddler==null) return false;
var out= [];
var row="";
var numDays= 31;//assume for now
var students=[];
if(classTiddler.fields){
for(var field in classTiddler.fields){
if(field.match(/^student/)!=null){
var SID = field.slice(field.match(/^student/)[0].toString().length);
if(!students.inArray(SID)) students.push(SID);
}
}
row= "|!SID";
for(var i=1;i<=numDays;i++){
row= row+"|!"+i;
}
row=row+"|";
out.push(row);
for(s=0;s<students.length;s++){
var row= "|"+students[s];
for(var i=1;i<=numDays;i++){
row= row+"|<<edit day"+i+">>";
}
row=row+"|";
out.push(row);
}
}
wikify(out.join('\n'), place);
</script>
<script>
var tid='$1';
if(tid==null) return false;
tid= store.getTiddler(tid);
var min= store.getValue(tid, 'min');
if(min===undefined || min===null) min=0;
var numDays=31; //assume for now
var students={};
var out=[];
for(field in tid.fields){
if(field.indexOf("day")!=-1){
var SID=field.substring(0, field.indexOf("day"));
if(students[SID]===undefined) students[SID]="";
}
}
for(s in students){
var tot=0;
for(var i=1;i<=numDays;i++){
var fld=s+"day"+i;
if(tid.fields[fld]=='p' || tid.fields[fld]=='P')
tot++;
}
students[s]=tot;
}
out.push(' ');
for(s in students){
if(students[s]<min)
out.push('[['+s+']]'+'('+(min-students[s])+') ')
}
if(out.length>1) out[0]='@@color:red;Minimum Req='+min+'. Following students are falling short:@@\n';
wikify(out.join(""),place);
</script>
<script>
var here=story.findContainingTiddler(place);
if(!here) return false;
var tid=here.getAttribute('tiddler');
if(!store.getTiddler(tid)) return false;
var parent = store.getTiddler(tid).fields.parent;
if(!parent) parent= 'None found';
var str="Parent: [["+parent+"]]";
wikify(str, place);
</script>
<script>
var SID = story.findContainingTiddler(place).getAttribute('tiddler');
var allQualTiddlers = store.getTaggedTiddlers('Qualification');
var allClassTiddlers = store.getTaggedTiddlers('Class');
var allTestTiddlers = store.getTaggedTiddlers('Test');
var enrolled = [];
var out = [];
out.push('!Qualifications');
for(var q=0;q<allQualTiddlers.length;q++)
if(allQualTiddlers[q].fields.parent == SID)
out.push('*[['+allQualTiddlers[q].fields.qualification_name+'|'+allQualTiddlers[q].title+']]');
out.push('!end');
out.push('!Classes');
for(var c=0;c<allClassTiddlers.length;c++)
if(allClassTiddlers[c].fields['student'+SID]!=null && allClassTiddlers[c].fields['student'+SID]=='true'){
out.push('*[['+allClassTiddlers[c].title+']]');
enrolled.push(allClassTiddlers[c].title);
}
out.push('!end');
out.push('!Grades');
out.push('|!Test|!Marks Obt|!Marks Maximum|!Percentage|!Result|!Grade|');
for(var t=0;t<allTestTiddlers.length;t++){
if(enrolled.inArray(allTestTiddlers[t].fields.parent, true)){
var test=allTestTiddlers[t].title;
var obt=allTestTiddlers[t].fields['marks'+SID];
var max=allTestTiddlers[t].fields['max_marks'];
var perc= (obt+0)/(max+0)*100;
var pass=allTestTiddlers[t].fields['pass_marks'];
var result;
(obt>=pass)?result='Pass':result='Fail';
var grade= allTestTiddlers[t].fields['grade'+SID]
out.push('|[['+test+']]|'+obt+'|'+max+'|'+perc+'|'+result+'|'+grade+'|');
}
}
out.push('!end');
var shadowTiddler = 'StudentData'+SID;
config.shadowTiddlers[shadowTiddler]=out.join('\n');
/*store.saveTiddler(shadowTiddler, shadowTiddler, out.join('\n'), config.options.txtUserName, new Date(),[],{});*/
return '<<tabs txtStudentData'+SID+' [[Qualifications]] "Qualifications" [['+shadowTiddler+'##Qualifications]] [[Classes]] "Classes" [['+shadowTiddler+'##Classes]] [[Grades]] "Grades" [['+shadowTiddler+'##Grades]]>>'
</script>
<script label="Click here to show enrolled students in separate tiddler">
var className= story.findContainingTiddler(place).getAttribute('tiddler');
if(className==null) return false;
var students=store.getTaggedTiddlers('Student');
var enrolled=[];
var out=[];
out.push("List of Students enrolled in class: "+className);
out.push('|Student Id|Name|h');
for(var s=0;s<students.length;s++){
if(store.getValue(className, 'student'+students[s].title)=='true') out.push('|'+students[s].title+'|'+students[s].fields.student_name+'|');
}
out.push('|sortable|k');
var shadowTiddler= className+"EnrolledStudentsList";
config.shadowTiddlers[shadowTiddler]=out.join('\n');
story.displayTiddler(null,shadowTiddler,'ViewTemplate',null,null);
</script>
<script>
var groups={};
var students=store.getTaggedTiddlers('Student');
var enrolled = 0;
var classTitle = story.findContainingTiddler(place).getAttribute('tiddler');
for (var s=0; s<students.length; s++) {
var g=students[s].fields.year_admission;
if (groups[g]===undefined) groups[g]=[];
groups[g].push(students[s]);
if(store.getValue(classTitle, 'student'+students[s].title)=='true') enrolled++;
}
var out=[];
for (var g in groups) {
out.push('!'+g);
var temp=[];
for (var s=0; s<groups[g].length; s++){
//out.push('*[['+groups[g][s].title+']] [_('+'student'+groups[g][s].title+'@'+classTitle+')]');
temp.push('[_(student'+groups[g][s].title+'@'+classTitle+')][['+groups[g][s].title+']]');
}
out.push(temp.join(' '));
out.push('!end');
}
var shadowTiddler = classTitle + 'StudentTabs';
config.shadowTiddlers[shadowTiddler]=out.join('\n');
var out=[];
for (var g in groups){
out.push('[['+g+']] [['+g+']] [['+shadowTiddler+'##'+g+']]');
}
var heading = 'There are '+students.length+' students in '+out.length+' groups and '+enrolled+' students are enrolled in this class<br>';
return heading+'<<tabs txtStudentTabs '+out.join(' ')+'>>';
</script>
keep a record of your classes & students @@float:right;<<tiddler ToggleRightSidebar with: [sidebar]>>@@
/***
|Name|SnapshotPlugin|
|Source|http://www.TiddlyTools.com/#SnapshotPlugin|
|Documentation|http://www.TiddlyTools.com/#SnapshotPluginInfo|
|Version|1.2.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|save or print HTML+CSS image of rendered document content|
|Status|ALPHA - DO NOT DISTRIBUTE|
This plugin provides a macro as well as tiddler toolbar commands to create a file or browser window containing the //rendered// CSS-and-HTML that is currently being displayed for selected elements of the current document.
!!!!!Documentation
>see [[SnapshotPluginInfo]]
!!!!!Configuration
<<<
<<option chkSnapshotHTMLOnly>> output HTML only (omit CSS)
<<<
!!!!!Revisions
<<<
2009.06.04 [1.2.0] added handling in getSnap() so current form input values are shown in snapshots
|please see [[SnapshotPluginInfo]] for additional revision details|
2008.04.21 [1.0.0] initial release - derived from [[NewDocumentPlugin]] with many improvements...
<<<
!!!!!Code
***/
//{{{
version.extensions.SnapshotPlugin= {major: 1, minor: 2, revision: 0, date: new Date(2009,6,4)};
if (config.options.chkSnapshotHTMLOnly===undefined) config.options.chkSnapshotHTMLOnly=false;
config.macros.snapshot = {
snapLabel: "save a snapshot",
printLabel: "print a snapshot",
snapPrompt: "save an HTML image of rendered content",
printPrompt: "print an HTML image of rendered content",
hereID: "here",
viewerID: "viewer",
storyID: "story",
allID: "all",
askID: "ask",
askTiddlerID: "askTiddler",
askDOMID: "askDOM",
askMsg: "select an element...",
hereItem: "tiddler: '%0'",
viewerItem: "tiddler: '%0' (content only)",
storyItem: "story column",
allItem: "entire document",
tiddlerItem: "select a tiddler...",
IDItem: "select a DOM element by ID...",
HTMLItem: "[%0] output HTML only (omit CSS)",
fileMsg: "select or enter a target path/filename",
defaultFilename: "snapshot.html",
okmsg: "snapshot written to %0",
failmsg: "An error occurred while creating %0",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var printing=params[0]&¶ms[0]=="print"; if (printing) params.shift();
params = paramString.parseParams("anon",null,true,false,false);
var id=getParam(params,"id","here");
var label=getParam(params,"label",printing?this.printLabel:this.snapLabel);
var prompt=getParam(params,"prompt",printing?this.printPrompt:this.snapPrompt);
var btn=createTiddlyButton(place,label,prompt, function(ev){
this.setAttribute("snapID",this.getAttribute("startID"));
config.macros.snapshot.go(this,ev)
});
btn.setAttribute("startID",id);
btn.setAttribute("snapID",id);
btn.setAttribute("printing",printing?"true":"false");
btn.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
},
go: function(here,ev) {
var cms=config.macros.snapshot; // abbreviation
var id=here.getAttribute("snapID");
var printing=here.getAttribute("printing")=="true";
var HTMLOnly=here.getAttribute("HTMLOnly")=="true";
if (id==cms.askID||id==cms.askTiddlerID||id==cms.askDOMID) {
cms.askForID(here,ev);
} else {
// get element
if (id==cms.storyID) id="tiddlerDisplay";
if (id==cms.allID) id="contentWrapper";
var snapElem=document.getElementById(id);
if (id==cms.hereID || id==cms.viewerID)
var snapElem=story.findContainingTiddler(here);
if (snapElem && hasClass(snapElem,"tiddler") && (id==cms.viewerID || HTMLOnly)) {
// find viewer class element within tiddler element
var nodes=snapElem.getElementsByTagName("*");
for (var i=0; i<nodes.length; i++)
if (hasClass(nodes[i],"viewer")) { snapElem=nodes[i]; break; }
}
if (!snapElem) // not in a tiddler or no viewer element or unknown ID
{ e.cancelBubble=true; if(e.stopPropagation)e.stopPropagation(); return(false); }
// write or print snapshot
var out=cms.getsnap(snapElem,id,printing,HTMLOnly);
if (printing) cms.printsnap(out); else cms.savesnap(out);
}
return false;
},
askForID: function(here,ev) {
var ev = ev ? ev : window.event;
var cms=config.macros.snapshot; // abbreviation
var id=here.getAttribute("snapID");
var indent='\xa0\xa0\xa0\xa0';
var p=Popup.create(here); if (!p) return false; p.className+=' sticky smallform';
var s=createTiddlyElement(p,'select'); s.button=here;
if (id==cms.askID) {
s.options[s.length]=new Option(cms.askMsg,cms.askID);
var tid=story.findContainingTiddler(here);
if(tid) {
var title=tid.getAttribute("tiddler");
if (here.getAttribute("HTMLOnly")!="true")
s.options[s.length]=new Option(indent+cms.hereItem.format([title]),cms.hereID);
s.options[s.length]=new Option(indent+cms.viewerItem.format([title]),cms.viewerID);
}
s.options[s.length]=new Option(indent+cms.tiddlerItem,cms.askTiddlerID);
s.options[s.length]=new Option(indent+cms.IDItem,cms.askDOMID);
s.options[s.length]=new Option(indent+cms.storyItem,"tiddlerDisplay");
s.options[s.length]=new Option(indent+cms.allItem,"contentWrapper");
}
if (id==cms.askDOMID) {
s.options[s.length]=new Option(cms.IDItem,cms.askDOMID);
var elems=document.getElementsByTagName("*");
var ids=[];
for (var i=0;i<elems.length;i++)
if (elems[i].id.length && elems[i].className!="animationContainer")
ids.push(elems[i].id);
ids.sort();
for (var i=0;i<ids.length;i++) s.options[s.length]=new Option(indent+ids[i],ids[i]);
}
if (id==cms.askTiddlerID) {
s.options[s.length]=new Option(cms.tiddlerItem,cms.askTiddlerID);
var elems=document.getElementsByTagName("div");
var ids=[];
for (var i=0;i<elems.length;i++) { var id=elems[i].id;
if (id.length && id.substr(0,story.idPrefix.length)==story.idPrefix && id!="tiddlerDisplay")
ids.push(id);
}
ids.sort();
for (var i=0;i<ids.length;i++) s.options[s.length]=new Option(indent+ids[i].substr(story.idPrefix.length),ids[i]);
}
s.options[s.length]=new Option(cms.HTMLItem.format([here.getAttribute("HTMLOnly")=="true"?"\u221a":"_"]),cms.HTMLItem);
s.onchange=function(ev){
var ev = ev ? ev : window.event;
var cms=config.macros.snapshot; // abbreviation
var here=this.button;
if (this.value==cms.HTMLItem) {
config.options.chkSnapshotHTMLOnly=!config.options.chkSnapshotHTMLOnly;
here.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
config.macros.option.propagateOption("chkSnapshotHTMLOnly","checked",
config.options.chkSnapshotHTMLOnly,"input");
} else
here.setAttribute("snapID",this.value);
config.macros.snapshot.go(here,ev);
return false;
};
Popup.show();
ev.cancelBubble=true;
if(ev.stopPropagation)ev.stopPropagation();
return false;
},
getpath: function() {
// get current path
var path=getLocalPath(window.location.href);
var slashpos=path.lastIndexOf("/");
if (slashpos==-1) slashpos=path.lastIndexOf("\\");
if (slashpos!=-1) path=path.substr(0,slashpos+1); // trim filename
return path;
},
getsnap: function(snapElem,id,printing,HTMLOnly) {
var cms=config.macros.snapshot; // abbreviation
var out='<head>\n';
if (printing)
out+='<base href="file:///'+cms.getpath().replace(/\\/g,'/')+'"></base>\n';
if (!HTMLOnly) {
var styles=document.getElementsByTagName('style');
var fmt='<style>\n/* stylesheet=%0 */\n%1\n\n</style>\n';
for(var i=0; i < styles.length; i++)
out+=fmt.format([styles[i].getAttribute('id'),styles[i].innerHTML]);
}
out+='</head>\n';
var elems=snapElem.getElementsByTagName('input');
for (var i=0; i<elems.length; i++) { var e=elems[i];
if (e.type=='text') e.defaultValue=e.value;
if (e.type=='checkbox') e.defaultChecked=e.checked;
if (e.type=='radiobutton') e.defaultChecked=e.checked;
}
var elems=snapElem.getElementsByTagName('textarea');
for (var i=0; i<elems.length; i++) elems[i].defaultValue=elems[i].value;
var fmt='<body>\n\n<div class="%0">%1</div>\n\n</body>\n';
out+=fmt.format([(id==cms.viewerID?'tiddler viewer':''),snapElem.innerHTML]);
return '<html>\n'+out+'</html>';
},
printsnap: function(out) {
var win=window.open("","_blank","");
win.document.open();
win.document.writeln(out);
win.document.close();
win.focus(); // bring to front
win.print(); // trigger print dialog
},
savesnap: function(out) {
var cms=config.macros.snapshot; // abbreviation
// make sure we are local
if (window.location.protocol!="file:")
{ alert(config.messages.notFileUrlError); return; }
var target=cms.askForFilename(cms.fileMsg,cms.getpath(),cms.defaultFilename);
if (!target) return; // cancelled by user
// if specified file does not include a path, assemble fully qualified path and filename
var slashpos=target.lastIndexOf("/");
if (slashpos==-1) slashpos=target.lastIndexOf("\\");
if (slashpos==-1) target=target+cms.defaultFilename;
var link="file:///"+target.replace(/\\/g,'/'); // link for message text
var ok=saveFile(target,convertUnicodeToUTF8(out));
var msg=ok?cms.okmsg.format([target]):cms.failmsg.format([target]);
clearMessage(); displayMessage(msg,link);
},
askForFilename: function(msg,path,file) {
if(window.Components) { // moz
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
picker.init(window, msg, nsIFilePicker.modeSave);
var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
thispath.initWithPath(path);
picker.displayDirectory=thispath;
picker.defaultExtension='html';
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XP/Vista only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
s.FilterIndex=3; // default to HTML files;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
}
return result;
}
};
//}}}
// // TOOLBAR DEFINITIONS
//{{{
config.commands.snapshotSave = {
text: "snap",
tooltip: config.macros.snapshot.snapPrompt,
handler: function(ev,src,title) {
src.setAttribute("snapID","ask");
src.setAttribute("printing","false");
src.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
config.macros.snapshot.go(src,ev);
return false;
}
};
config.commands.snapshotPrint = {
text: "print",
tooltip: config.macros.snapshot.printPrompt,
handler: function(ev,src,title) {
src.setAttribute("snapID","ask");
src.setAttribute("printing","true");
src.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
config.macros.snapshot.go(src,ev);
return false;
}
};
//}}}
// // COPIED FROM [[StickyPopupPlugin]] TO ELIMINATE PLUGIN DEPENDENCY
//{{{
if (config.options.chkStickyPopups==undefined) config.options.chkStickyPopups=false;
Popup.stickyPopup_onDocumentClick = function(ev)
{
// if click is in a sticky popup, ignore it so popup will remain visible
var e = ev ? ev : window.event; var target = resolveTarget(e);
var p=target; while (p) {
if (hasClass(p,"popup") && (hasClass(p,"sticky")||config.options.chkStickyPopups)) break;
else p=p.parentNode;
}
if (!p) // not in sticky popup (or sticky popups disabled)... use normal click handling
Popup.onDocumentClick(ev);
return true;
};
try{removeEvent(document,"click",Popup.onDocumentClick);}catch(e){};
try{addEvent(document,"click",Popup.stickyPopup_onDocumentClick);}catch(e){};
//}}}
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro='tiddler MoveTiddlerToTop'></span>
<span macro='tiddler ScrollToTop'></span>
<div class='toolbar border' macro='toolbar [[ToolbarCommands::EditRecordToolbar]]'></div>
<h1>Student</h1>
<div class='viewer'>
<table class="editRecord">
<tr><td>Student Id:<br><i>unique, alphanumeric, no spaces</i></td><td><span macro="edit title"></span></td></tr>
<tr><td>Name:</td><td> <span macro='edit student_name'> </span> </td></tr>
<tr><td>Date of Admission:</td><td><span macro='select date_admission rows:1 *DatesList'></span>-<span macro='select month_admission rows:1 *MonthsList'></span>-<span macro='select year_admission rows:1 *YearsList'></span></td></tr>
<tr><td>Father's Name:</td><td><span macro='edit father_name'> </span> </td></tr>
<tr><td>Mother's Name:</td><td><span macro='edit mother_name'> </span></td></tr>
<tr><td>Date of Birth:</td><td><span macro='select date_birth rows:1 *DatesList'></span>-<span macro='select month_birth rows:1 *MonthsList'></span>-<span macro='select year_birth rows:1 *YearsList'></span></td></tr>
<tr><td>Sex:</td><td><span macro='select sex rows:1 "Male" "Female"'> </span></td></tr>
<tr><td>Email:</td><td><span macro='edit email'></span></td></tr>
<tr><td>Phones:<br><i>separate with commas</i></td><td><span macro='edit phones'></span></td></tr>
<tr><td>Address:</td><td><span macro='edit address 5'></span></td></tr>
</table>
<div style="display:none;" class='editor' macro='edit tags'></div>
</div>
<!--}}}-->
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro='tiddler MoveTiddlerToTop'></span>
<span macro='tiddler ScrollToTop'></span>
<div class="toolbar border" macro="toolbar [[ToolbarCommands::EditRecordToolbar]]"></div>
<h1> Student Group</h1>
<div class="viewer">
<table style="">
<tr><td>Name:<br><i>(alphanumeric with no spaces eg.StuGrp0809)</i></td><td><span macro="edit title"></span></td></tr>
<tr>
<td>Admission Date:</td><td><span macro="edit admission_date"></span></td>
</tr>
<tr>
<td>Remarks:</td><td><span macro="edit remarks 5"></span></td>
</tr></table>
</div>
<div macro="edit tags" style="display: none"></div>
<!--}}}-->
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro='tiddler MoveTiddlerToTop'></span>
<span macro='tiddler ScrollToTop'></span>
<div class="toolbar border" macro="toolbar [[ToolbarCommands::ViewToolbar]]"><span style="color:#ccc;">[</span>change:»<span style="padding-right:0em;" macro='tagger'></span ><span style="color:#ccc">]</span></div>
<h1>Student Group</h1>
<div class="viewer">
<table class='record'>
<tr><td><b>Student Group:</b></td><td><b><span macro="view title"></span></b></td></tr>
<tr><td>Admission Date:</td><td><span macro="view admission_date"></span></td></tr>
<tr><td>Remarks:</td><td><span macro="view remarks 5"></span></td></tr>
</table>
<div class='buttonbar'><span macro='tiddler "Add Student"'></span></div>
</div>
<!--}}}-->
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro="tiddler MoveTiddlerToTop"></span>
<span macro="tiddler ScrollToTop"></span>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
</div>
<div class='title' macro='view title'>Student Id: </div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class="viewer" >
<table class='viewRecord'>
<tr><td class='alignR'>Name:</td><td class='alignL'> <span macro='view student_name'> </span> </td></tr>
<tr><td>Date of Admission:</td><td><span macro='view date_admission'></span>-<span macro='view month_admission'></span>-<span macro='view year_admission'></span></td></tr>
<tr><td class='alignR'>Father's Name:</td><td class='alignL'><span macro='view father_name'> </span> </td></tr>
<tr><td class='alignR'>Mother's Name:</td><td class='alignL'><span macro='view mother_name'> </span></td></tr>
<tr><td>Date of Birth:</td><td><span macro='view date_birth'></span>-<span macro='view month_birth'></span>-<span macro='view year_birth'></span></td></tr>
<tr><td class='alignR'>Sex:</td><td class='alignL'><span macro='view sex'> </span></td></tr>
<tr><td class='alignR'>Email:</td><td class='alignL'><span macro='view email'></span></td></tr>
<tr><td class='alignR'>Phones:</td><td class='alignL'><span macro='view phones'></span></td></tr>
<tr><td class='alignR'>Address:</td><td class='alignL'><span macro='view address'></span></td></tr>
</table>
<div class="recordToolbar"><span macro="tiddler 'Add Qualification'"></span></div>
<span macro='tiddler ShowStudentDataTabs'></span>
</div>
<!--}}}-->
.headerShadow{
padding: 1em;
text-align: center;
}
#displayArea {
margin:1em 17em 0 1em;
}
#topMenu{
text-align:left;
background-color: #f0f0f0;
padding: 8px 0 8px 8px;
}
#topMenu a{
color:#404040;
font-weight: bold;
border: 1px solid #707070;
padding: 2px;
}
#topMenu a:hover{
color: #104E8B;
background: white;
}
.headerForeground, .headerShadow{padding:.5em;}
.tiddler ol li{
margin-top: 1em;
}
/***
|''Name:''|TableSortingPlugin|
|''Description:''|Dynamically sort tables by clicking on column headers|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TableSortingPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.02|
|''Date:''|25-01-2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Usage:
* Make sure your table has a header row
** {{{|Name|Phone Number|Address|h}}}<br> Note the /h/ that denote a header row
* Give the table a class of 'sortable'
** {{{
|sortable|k
|Name|Phone Number|Address|h
}}}<br>Note the /k/ that denotes a class name being assigned to the table.
* To disallow sorting by a column, place {{{<<nosort>>}}} in it's header
* To automatically sort a table by a column, place {{{<<autosort>>}}} in the header for that column
** Or to sort automatically but in reverse order, use {{{<<autosort reverse>>}}}
!!Example:
|sortable|k
|Name |Salary |Extension |Performance |File Size |Start date |h
|ZBloggs, Fred |$12000.00 |1353 |+1.2 |74.2Kb |Aug 19, 2003 21:34:00 |
|ABloggs, Fred |$12000.00 |1353 |1.2 |3350b |09/18/2003 |
|CBloggs, Fred |$12000 |1353 |1.200 |55.2Kb |August 18, 2003 |
|DBloggs, Fred |$12000.00 |1353 |1.2 |2100b |07/18/2003 |
|Bloggs, Fred |$12000.00 |1353 |01.20 |6.156Mb |08/17/2003 05:43 |
|Turvey, Kevin |$191200.00 |2342 |-33 |1b |02/05/1979 |
|Mbogo, Arnold |$32010.12 |2755 |-21.673 |1.2Gb |09/08/1998 |
|Shakespeare, Bill |ã122000.00|3211 |6 |33.22Gb |12/11/1961 |
|Shakespeare, Hamlet |ã9000 |9005 |-8 |3Gb |01/01/2002 |
|Fitz, Marvin |â¬3300.30 |5554 |+5 |4Kb |05/22/1995 |
***/
// /%
//!BEGIN-PLUGIN-CODE
config.tableSorting = {
darrow: "\u2193",
uarrow: "\u2191",
getText : function (o) {
var p = o.cells[SORT_INDEX];
return p.innerText || p.textContent || '';
},
sortTable : function (o,rev) {
SORT_INDEX = o.getAttribute("index");
var c = config.tableSorting;
var T = findRelated(o.parentNode,"TABLE");
if(T.tBodies[0].rows.length<=1)
return;
var itm = "";
var i = 0;
while (itm == "" && i < T.tBodies[0].rows.length) {
itm = c.getText(T.tBodies[0].rows[i]).trim();
i++;
}
if (itm == "")
return;
var r = [];
var S = o.getElementsByTagName("span")[0];
c.fn = c.sortAlpha;
if(!isNaN(Date.parse(itm)))
c.fn = c.sortDate;
else if(itm.match(/^[$|ã|â¬|\+|\-]{0,1}\d*\.{0,1}\d+$/))
c.fn = c.sortNumber;
else if(itm.match(/^\d*\.{0,1}\d+[K|M|G]{0,1}b$/))
c.fn = c.sortFile;
for(i=0; i<T.tBodies[0].rows.length; i++) {
r[i]=T.tBodies[0].rows[i];
}
r.sort(c.reSort);
if(S.firstChild.nodeValue==c.darrow || rev) {
r.reverse();
S.firstChild.nodeValue=c.uarrow;
}
else
S.firstChild.nodeValue=c.darrow;
var thead = T.getElementsByTagName('thead')[0];
var headers = thead.rows[thead.rows.length-1].cells;
for(var k=0; k<headers.length; k++) {
if(!hasClass(headers[k],"nosort"))
addClass(headers[k].getElementsByTagName("span")[0],"hidden");
}
removeClass(S,"hidden");
for(i=0; i<r.length; i++) {
T.tBodies[0].appendChild(r[i]);
c.stripe(r[i],i);
for(var j=0; j<r[i].cells.length;j++){
removeClass(r[i].cells[j],"sortedCol");
}
addClass(r[i].cells[SORT_INDEX],"sortedCol");
}
},
stripe : function (e,i){
var cl = ["oddRow","evenRow"];
i&1? cl.reverse() : cl;
removeClass(e,cl[1]);
addClass(e,cl[0]);
},
sortNumber : function(v) {
var x = parseFloat(this.getText(v).replace(/[^0-9.-]/g,''));
return isNaN(x)? 0: x;
},
sortDate : function(v) {
return Date.parse(this.getText(v));
},
sortAlpha : function(v) {
return this.getText(v).toLowerCase();
},
sortFile : function(v) {
var j, q = config.messages.sizeTemplates, s = this.getText(v);
for (var i=0; i<q.length; i++) {
if ((j = s.toLowerCase().indexOf(q[i].template.replace("%0\u00a0","").toLowerCase())) != -1)
return q[i].unit * s.substr(0,j);
}
return parseFloat(s);
},
reSort : function(a,b){
var c = config.tableSorting;
var aa = c.fn(a);
var bb = c.fn(b);
return ((aa==bb)? 0 : ((aa<bb)? -1:1));
}
};
Story.prototype.tSort_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText){
var elem = this.tSort_refreshTiddler.apply(this,arguments);
if(elem){
var tables = elem.getElementsByTagName("TABLE");
var c = config.tableSorting;
for(var i=0; i<tables.length; i++){
if(hasClass(tables[i],"sortable")){
var x = null, rev, table = tables[i], thead = table.getElementsByTagName('thead')[0], headers = thead.rows[thead.rows.length-1].cells;
for (var j=0; j<headers.length; j++){
var h = headers[j];
if (hasClass(h,"nosort"))
continue;
h.setAttribute("index",j);
h.onclick = function(){c.sortTable(this); return false;};
h.ondblclick = stopEvent;
if(h.getElementsByTagName("span").length == 0)
createTiddlyElement(h,"span",null,"hidden",c.uarrow);
if(!x && hasClass(h,"autosort")) {
x = j;
rev = hasClass(h,"reverse");
}
}
if(x)
c.sortTable(headers[x],rev);
}
}
}
return elem;
};
setStylesheet("table.sortable span.hidden {visibility:hidden;}\n"+
"table.sortable thead {cursor:pointer;}\n"+
"table.sortable .nosort {cursor:default;}\n"+
"table.sortable td.sortedCol {background:#ffc;}","TableSortingPluginStyles");
function stopEvent(e){
var ev = e? e : window.event;
ev.cancelBubble = true;
if (ev.stopPropagation) ev.stopPropagation();
return false;
}
config.macros.nosort={
handler : function(place){
addClass(place,"nosort");
}
};
config.macros.autosort={
handler : function(place,m,p,w,pS){
addClass(place,"autosort"+" "+pS);
}
};
//!END-PLUGIN-CODE
// %/
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for specific tiddlers|
This plugin extends the core function, story.chooseTemplateForTiddler(), so that any given tiddler can be viewed and/or edited using alternatives to the standard tiddler templates.
!!!!!Documentation
>see [[TaggedTemplateTweakInfo]]
!!!!!Revisions
<<<
2009.07.31 [1.6.0] added support for using custom field value as prefix
| please see [[TaggedTemplateTweakInfo]] for previous revision details |
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TaggedTemplateTweak= {major: 1, minor: 6, revision: 0, date: new Date(2009,7,31)};
if (!config.options.txtTemplateTweakFieldname)
config.options.txtTemplateTweakFieldname='template';
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
// get core template and split into theme and template name
var coreTemplate=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
var theme=""; var template=coreTemplate;
var parts=template.split(config.textPrimitives.sectionSeparator);
if (parts[1]) { theme=parts[0]; template=parts[1]; }
else theme=config.options.txtTheme||""; // if theme is not specified
theme+=config.textPrimitives.sectionSeparator;
// look for template using title as prefix
if (!store.getTaggedTiddlers(title).length) { // if tiddler is not a tag
if (store.getTiddlerText(theme+title+template))
{ return theme+title+template; } // theme##TitleTemplate
if (store.getTiddlerText(title+template))
{ return title+template; } // TitleTemplate
}
// look for template using tags as prefix
var tiddler=store.getTiddler(title);
if (!tiddler) return coreTemplate; // tiddler doesn't exist... use core result
for (i=0; i<tiddler.tags.length; i++) {
var t=tiddler.tags[i]+template; // add tag prefix to template
var c=t.substr(0,1).toUpperCase()+t.substr(1); // capitalized for WikiWord title
if (store.getTiddlerText(theme+t)) { return theme+t; } // theme##tagTemplate
if (store.getTiddlerText(theme+c)) { return theme+c; } // theme##TagTemplate
if (store.getTiddlerText(t)) { return t; } // tagTemplate
if (store.getTiddlerText(c)) { return c; } // TagTemplate
}
// look for templates using custom field value as prefix
var v=store.getValue(title,config.options.txtTemplateTweakFieldname);
if (store.getTiddlerText(theme+v+template))
{ return theme+v+template; } // theme##valueTemplate
if (store.getTiddlerText(v+template))
{ return v+template; } // valueTemplate
// no match... use core result
return coreTemplate;
}
//}}}
/***
|Name|TaggedTemplateTweakInfo|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for TaggedTemplateTweak|
This plugin extends the core function, story.chooseTemplateForTiddler(), so that any given tiddler can be viewed and/or edited using alternatives to the standard tiddler templates. To select alternative templates, a 'template prefix' is determined by using the tiddler's title or matching a tag value or using a value stored in a custom tiddler field.
!!!!!Usage
<<<
The plugin first attempts to use the tiddler's //title// as a prefix added to the standard TiddlyWiki template titles, [[ViewTemplate]] and [[EditTemplate]] (i.e., ''TiddlerNameViewTemplate'' and ''TiddlerNameEditTemplate''). This allows you to associate a custom template with a specific tiddler, without needing to add any special tags or custom field values to that individual tiddler.
Next, if no template is found using the title, each of the tiddler's tags is tried as a template prefix, until a corresponding template, if any, is found. For example, any tiddlers that are tagged with ''<<tag media>>'' could find alternative templates named [[mediaViewTemplate]] and [[mediaEditTemplate]].
*To permit use of templates that have proper WikiWord tiddler titles (e.g., [[MediaViewTemplate]] and [[MediaEditTemplate]]), the plugin also attempts to use a capitalized form of the tag value (e.g., ''Media'') as a prefix. //This capitalization is for comparison purposes only and will not alter the actual tag values that are stored in the tiddler.//
*If you are applying a systemTheme definition, the plugin also tries prepending the currently selected theme (specified by {{{config.options.txtTheme}}}) plus the 'section separator' (##) to the template name (e.g. ''[[SomeTheme##MediaViewTemplate]]'') so that the alternative template definitions can be contained as //sections// within a single systemTheme tiddler.
You can also define a tiddler's template prefix by using a //custom tiddler field// named 'template'. If no corresponding template was found using either the title or a matching tag, then the tiddler's 'template' field value, if present, will be used as a prefix (e.g., if template='SomeThing', then [[SomeThingViewTemplate]] will be applied).
*You can redefine the //name// of the custom field used to store the template prefix. For example, to use the name of a TiddlyWeb server-side 'bag' as a prefix (so that tiddlers from separate bags can have different appearances), add the following to a tiddler tagged with<<tag systemConfig>>:
{{{
config.options.txtTemplateTweakFieldname='server.bag'; // use TiddlyWeb bag name as prefix
}}}
Lastly, if no alternative template is found at all, the standard [[ViewTemplate]] or [[EditTemplate]] definition as determined by the TiddlyWiki core handler is used.
''To add your own custom templates:''
>First, decide upon a suitable tag keyword to uniquely identify your custom templates and create custom view and/or edit templates using that keyword as a prefix (e.g., "KeywordViewTemplate" and "KeywordEditTemplate"). Then, simply create a tiddler and tag it with your chosen keyword... that's it! As long as the tiddler is tagged with your keyword, it will be displayed using the corresponding alternative templates. If you remove the tag or rename/delete the alternative templates, the tiddler will revert to using the standard viewing and editing templates.
<<<
!!!!!Examples
<<<
|Sample tiddler| tag | view template | edit template |
|[[MediaSample - QuickTime]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[MediaSample - Windows]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[CDSample]]| <<tag CD>> | [[CDViewTemplate]] | [[CDEditTemplate]] |
|<<newTiddler label:"create new task..." title:SampleTask tag:task text:"Type some text and then press DONE to view the task controls">> | <<tag task>> | [[TaskViewTemplate]] | [[EditTemplate]] |
//(note: if these samples are not present in your document, please visit// http://www.TiddlyTools.com/ //to view these sample tiddlers on-line)//
<<<
!!!!!Revisions
<<<
2009.07.31 [1.6.0] added support for using custom field value as prefix
2009.05.04 [1.5.2] check for tiddler exist *after* title-as-prefix (allows shadow tiddlers to use custom templates)
2009.01.06 [1.5.1] reversed logic so that title-as-prefix takes precedence over tag-matched prefix
2008.12.18 [1.5.0] added handling for using tiddler //title// as prefix (e.g., {{{SomeTiddlerViewTemplate}}})
2008.08.29 [1.4.1] corrected handling for tiddlers with no matching tagged template when non-default theme is in effect (e.g., use "MyTheme##ViewTemplate").
2008.05.15 [1.4.0] support use of *shadow* tagged templates (e.g., [[DiscussionViewTemplate]] created by [[DiscussionPlugin]])
2008.05.10 [1.3.0] corrected handling for determining core template when using theme with sections
2008.05.01 [1.2.5] added support for tagged templates stored as sections in a theme
2008.04.01 [1.2.0] added support for using systemTheme section-based template definitions (requested by Phil Hawksworth)
2008.01.22 [*.*.*] plugin size reduction - documentation moved to [[TaggedTemplateTweakInfo]]
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag. Allows new custom tags to be used without requiring code changes to this plugin.
2007.06.11 [1.0.0] initial release
<<<
/***
|''Name:''|~TaggerPlugin|
|''Version:''|1.0.1 (2006-06-01)|
|''Source:''|http://tw.lewcid.org//#TaggerPlugin|
|''Author:''|SaqImtiaz|
|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|
|''Documentation:''|[[TaggerPluginDocumentation]]|
|''Source Code:''|[[TaggerPluginSource]]|
|''~TiddlyWiki:''|Version 2.0.8 or better|
|''Requires''|[[DeprecatedFunctionsPlugin]]|
|''Stylesheet Changes''|ViewTemplate|
|See Above|<div class='toolbar'><span style="padding-right:2.45em;" macro='tagger source:TagDB exclude:excludeLists'></span></div>|
***/
//{{{
config.tagger={
defaults:{
label: 'Tags: ',
tooltip: 'Manage tiddler tags',
taglist: 'true',
excludeTags: 'excludeLists',
notags: 'tiddler has no tags',
aretags: 'current tiddler tags:',
toggletext: 'add tags:'
}
};
config.macros.tagger={};
config.macros.tagger.arrow = (document.all?"▼":"▾"); // the fat one is the only one that works in IE
config.macros.tagger.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var defaults = config.tagger.defaults;
var nAV = paramString.parseParams('tagman', null, true);
var label = ((nAV[0].label)&&(nAV[0].label[0])!='.')?nAV[0].label[0]+this.arrow: defaults.label+this.arrow;
var tooltip = ((nAV[0].tooltip)&&(nAV[0].tooltip[0])!='.')?nAV[0].tooltip[0]: defaults.tooltip;
var taglist = ((nAV[0].taglist)&&(nAV[0].taglist[0])!='.')?nAV[0].taglist[0]: defaults.taglist;
var exclude = ((nAV[0].exclude)&&(nAV[0].exclude[0])!='.')?(nAV[0].exclude[0]).readBracketedList(): defaults.excludeTags.readBracketedList();
if ((nAV[0].source)&&(nAV[0].source[0])!='.')var source = nAV[0].source[0];
if (source&&!store.getTiddler(source)) return false;
var onclick = function(e) {
if (!e) var e = window.event;
var popup = Popup.create(this);
var tagsarray = store.getTags();
var tags=new Array();
for (var i=0; i<tagsarray.length; i++){
tags.push(tagsarray[i][0]);}
if (source)
{var sourcetiddler=store.getTiddler(source);
tags=sourcetiddler.tags.sort();}
var currentTags = tiddler.tags.sort();
var createButtons=function(text,theTag,tooltipPrefix){
var sp = createTiddlyElement(createTiddlyElement(popup,"li"),"span",null,"tagger");
var theToggle = createTiddlyButton(sp,text,tooltipPrefix+" '"+theTag+"'",taggerOnToggle,"button","toggleButton");
theToggle.setAttribute("tiddler",tiddler.title);
theToggle.setAttribute("tag",theTag);
insertSpacer(sp);
if (window.createTagButton_orig_mptw)
createTagButton_orig_mptw(sp,theTag);
else
createTagButton(sp,theTag);
}
createTiddlyElement(popup,"li",null,"listTitle",(tiddler.tags.length == 0 ? defaults.notags : defaults.aretags));
for (var t=0; t<currentTags.length; t++){
createButtons("[x]",currentTags[t],"remove tag ");
}
createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
if (taglist!='false')
{ createTiddlyElement(popup,"li",null,"listTitle",defaults.toggletext);
for (var i=0; i<tags.length; i++){
if (!tiddler.tags.contains(tags[i])&&!exclude.contains(tags[i]))
{createButtons("[ ]",tags[i],"add tag ");
}
}
createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
}
var newTagButton = createTiddlyButton(createTiddlyElement(popup,"li"),("Create new tag"),null,taggerOnToggle);
newTagButton.setAttribute("tiddler",tiddler.title);
if (source) newTagButton.setAttribute("source",source);
Popup.show(popup,false);
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
};
createTiddlyButton(place,label,tooltip,onclick,"button","taggerDrpBtn");
};
window.taggerOnToggle = function(e) {
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
var tiddler = store.getTiddler(title);
if (!tag)
{
var newtag=prompt("Enter new tag:","");
if (newtag!=''&&newtag!=null)
{
var tag=newtag;
if (this.getAttribute("source"))
{var sourcetiddler = store.getTiddler(this.getAttribute("source"));
sourcetiddler.tags.pushUnique(newtag);}
}
else
{return false;};
}
if (!tiddler || !tiddler.tags)
{store.saveTiddler(title,title,'',config.options.txtUserName,new Date(),tag);}
else
{if (tiddler.tags.find(tag)==null)
{tiddler.tags.push(tag)}
else if(!newtag)
{tiddler.tags.splice(tiddler.tags.find(tag),1)};
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags);};
story.refreshTiddler(title,null,true);
if(config.options.chkAutoSave)
saveChanges();
return false;
};
setStylesheet(
".tagger a.button {font-weight: bold;display:inline; padding:0px;}\n"+
".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\n"+
"#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\n"+
".popup .listTitle {color:#000;}\n"+
"",
"TaggerStyles");
window.lewcidTiddlerSwapTag = function (tiddler, oldTag, newTag){
for (var i = 0; i < tiddler.tags.length; i++)
if (tiddler.tags[i] == oldTag) {
tiddler.tags[i] = newTag;
return true;}
return false;
}
window.lewcidRenameTag = function(e) {
var tag=this.getAttribute("tag");
var newtag=prompt("Rename tag '"+tag+"' to:",tag);
if ((newtag==tag)||(newtag==null)) {return false;}
if(store.tiddlerExists(newtag))
{if(confirm(config.messages.overwriteWarning.format([newtag.toString()])))
story.closeTiddler(newtag,false,false);
else
return null;}
tagged=store.getTaggedTiddlers(tag);
if (tagged.length!=0){
for (var j = 0; j < tagged.length; j++)
lewcidTiddlerSwapTag(tagged[j],tag,newtag);}
if (store.tiddlerExists(tag))
{store.saveTiddler(tag,newtag);}
if (document.getElementById("tiddler"+tag))
{var oldTagTiddler = document.getElementById(story.idPrefix + tag);
var before= story.positionTiddler(oldTagTiddler);
var place = document.getElementById(story.container);
story.closeTiddler(tag,false,false);
story.createTiddler(place,before,newtag,null);
story.saveTiddler(newtag);}
if(config.options.chkAutoSave)
saveChanges();
return false;
}
window.onClickTag=function(e)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
var nested = (!isNested(theTarget));
if ((Popup.stack.length > 1)&&(nested==true)) {Popup.removeFrom(1);}
else if(Popup.stack.length > 0 && nested==false) {Popup.removeFrom(0);};
var theId = (nested==false)? "popup" : "nestedtagger";
var popup = createTiddlyElement(document.body,"ol",theId,"popup",null);
Popup.stack.push({root: this, popup: popup});
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
if(popup && tag)
{
var tagged = store.getTaggedTiddlers(tag);
var titles = [];
var li,r;
for(r=0;r<tagged.length;r++)
if(tagged[r].title != title)
titles.push(tagged[r].title);
var lingo = config.views.wikified.tag;
if(titles.length > 0)
{
var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
openAll.setAttribute("tag",tag);
createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
for(r=0; r<titles.length; r++)
{
createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
}
}
else
createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));
createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
createTiddlyText(h,lingo.openTag.format([tag]));
createTiddlyElement(createTiddlyElement(popup,"li"),"hr");
var renameTagButton = createTiddlyButton(createTiddlyElement(popup,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);
renameTagButton.setAttribute("tag",tag)
}
Popup.show(popup,false);
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
if (!window.isNested)
window.isNested = function(e) {
while (e != null) {
var contentWrapper = document.getElementById("contentWrapper");
if (contentWrapper == e) return true;
e = e.parentNode;
}
return false;
};
config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://tw.lewcid.org/#TaggerPluginDocumentation]]";
config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://tw.lewcid.org/#TaggerPluginSource]]";
//}}}
<!--{{{-->
<span macro='tiddler ClassRecordsStyleSheet'></span>
<span macro="tiddler MoveTiddlerToTop"></span>
<span macro="tiddler ScrollToTop"></span>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
</div>
<div class='title' macro='view title'>Test Id: </div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class="viewer" macro='view text wikified'>
<span macro='tiddler ShowParent'></span>
<table class="viewRecord">
<tr><td class='alignR'>Topic(s):</td><td class='alignL'><span macro='view topics'></span></td></tr>
<tr><td class='alignR'>Maximum Marks:</td><td class='alignL'><span macro="view max_marks"></span></td></tr>
<tr><td class='alignR'>Pass Marks:</td><td class='alignL'><span macro="view pass_marks"></span></td></tr>
<tr><td class='alignR'>Date:</td><td class='alignL'><span macro="view date"></span>-<span macro="view month"></span>-<span macro="view year"></span></td></tr>
</table>
<span macro='tiddler ViewStudentsPerformance'></span>
</div>
<span macro='tiddler CustomTestTemplate with:{{tiddler.title}}'></span>
<!--}}}-->
/***
|Name|TextAreaPlugin|
|Source|http://www.TiddlyTools.com/#TextAreaPlugin|
|Documentation|http://www.TiddlyTools.com/#TextAreaPluginInfo|
|Version|2.2.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.focusTiddler|
|Options|##Configuration|
|Description|Adds Find/Again keyboard search, autosize, and 'stretch bar' resize for textarea controls|
!!!!!Documentation
>see [[TextAreaPluginInfo]]
!!!!!Configuration
<<<
<<option chkTextAreaExtensions>> use control-f (find), control-g (find again) inside text area
<<option chkDisableAutoSelect>> place cursor at start of textarea instead of pre-selecting content
<<option chkResizeEditor>> modify shadow EditTemplate to add resizeable text area (and autosize command)
<<<
!!!!!Revisions
<<<
2009.04.08 [2.2.1] added autosizeEditor macro to enable automatic autosizing without using toolbar command
2009.04.06 [2.2.0] added resizeListbox macro definition and adjusted dragbar width calculation.
|please see [[TextAreaPluginInfo]] for additional revision details|
2006.01.22 [1.0.0] Moved from temporary "System Tweaks" tiddler into 'real' TextAreaPlugin tiddler.
<<<
!!!!!Code
***/
//{{{
version.extensions.TextAreaPlugin= {major: 2, minor: 2, revision: 1, date: new Date(2009,4,8)};
if (config.options.chkTextAreaExtensions===undefined) config.options.chkTextAreaExtensions=true;
if (config.options.chkDisableAutoSelect===undefined) config.options.chkDisableAutoSelect=true;
if (config.options.chkResizeEditor===undefined) config.options.chkResizeEditor=true;
// automatically tweak shadow EditTemplate to add "autosizeEditor" toolbar command
if (config.options.chkResizeEditor)
config.shadowTiddlers.EditTemplate=config.shadowTiddlers.EditTemplate.replace(/deleteTiddler/,"deleteTiddler autosizeEditor");
// automatically tweak shadow EditTemplate to add "resizeEditor" macro
if (config.options.chkResizeEditor)
config.shadowTiddlers.EditTemplate+="<span macro='resizeEditor'></span>";
// Put focus in a specified tiddler field
Story.prototype.TextAreaExtensions_focusTiddler=Story.prototype.focusTiddler;
Story.prototype.focusTiddler = function(title,field)
{
this.TextAreaExtensions_focusTiddler.apply(this,arguments); // first call core
var e = this.getTiddlerField(title,field);
if (e && config.options.chkDisableAutoSelect) {
if (e.setSelectionRange) // FF
e.setSelectionRange(0,0);
else if (e.createTextRange) // IE
{ var r=e.createTextRange(); r.collapse(true); r.select(); }
}
if (e && config.options.chkTextAreaExtensions) addKeyDownHandlers(e);
}
//}}}
//{{{
function addKeyDownHandlers(e)
{
// exit if not textarea or element doesn't allow selections
if (e.tagName.toLowerCase()!="textarea"||!e.setSelectionRange||e.initialized) return;
// utility function: exits keydown handler and prevents browser from processing the keystroke
var processed=function(ev) {
ev.cancelBubble=true; // IE4+
try{event.keyCode=0;}catch(e){}; // IE5
if (window.event) ev.returnValue=false; // IE6
if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
if (ev.stopPropagation) ev.stopPropagation(); // all
return false;
}
// capture keydown in edit field
e.saved_onkeydown=e.onkeydown; // save current keydown handler (if any)
e.onkeydown=function(ev) { if (!ev) var ev=window.event;
var key=ev.keyCode;
if (!key) {
var char=event.which?event.which:event.charCode;
if (char==102) key=70;
if (char==103) key=71;
}
// process CTRL-F (find matching text) or CTRL-G (find next match)
if (ev.ctrlKey && (key==70||key==71)) {
// prompt for text to find
var defFind=e.findText?e.findText:e.value.substring(e.selectionStart,e.selectionEnd);
if (key==70||!e.findText||!e.findText.length) // ctrl-f or no saved search text
{ var f=prompt("find:", defFind); e.focus(); if (f) e.findText=f; }
if (!e.findText||!e.findText.length) return processed(ev); // if no search text, exit
// do case-insensitive match with 'wraparound'... if not found, alert and exit
var newstart=e.value.toLowerCase().indexOf(e.findText.toLowerCase(),e.selectionStart+1);
if (newstart==-1) newstart=e.value.toLowerCase().indexOf(e.findText.toLowerCase());
if (newstart==-1) { alert("'"+e.findText+"' not found"); e.focus(); return processed(ev); }
// set new selection, scroll it into view, and report line position in status bar
e.setSelectionRange(newstart,newstart+e.findText.length);
var linecount=e.value.split('\n').length;
var thisline=e.value.substr(0,e.selectionStart).split('\n').length;
e.scrollTop=Math.floor((thisline-1-e.rows/2)*e.scrollHeight/linecount);
window.status="line: "+thisline+"/"+linecount;
return processed(ev);
}
if (e.saved_onkeydown) // call previous keydown handler (if any)
e.saved_onkeydown(ev);
}
e.initialized=true;
}
//}}}
// // 'autosize' toolbar command
//{{{
config.commands.autosizeEditor = {
text: 'autosize',
tooltip: 'automatically adjust the editor height to fit the contents',
text_alt: '\u221Aautosize',
hideReadOnly: false,
handler: function(event,src,title) {
var here=story.findContainingTiddler(src); if (!here) return;
var ta=here.getElementsByTagName('textarea'); if (!ta) return;
for (i=0;i<ta.length;i++) {
// only autosize textareas actually used to edit tiddler fields
if (ta[i].getAttribute("edit")==undefined) continue;
ta[i].button=src;
if (!ta[i].maxed)
config.commands.autosizeEditor.on(ta[i]);
else
config.commands.autosizeEditor.off(ta[i],true);
}
return false;
},
on: function(e) {
if (e.maxed) return; // already autosizing!
if (e.savedheight==undefined)
e.savedheight=e.style.height;
if (e.savedkeyup==undefined) {
e.savedkeyup=e.onkeyup;
e.onkeyup=function(ev) {
if (!ev) var ev=window.event; var e=resolveTarget(ev);
e.style.height=e.scrollHeight+'px';
if (e.savedkeyup) e.savedkeyup();
}
}
// IE reports error: "not implemented" for onkeypress
if (!config.browser.isIE && e.savedkeypress==undefined) {
e.savedkeypress=e.onkeypress;
e.onkeypress=function(ev) {
if (!ev) var ev=window.event; var e=resolveTarget(ev);
if (ev.keyCode==33) { // PGUP
if (window.scrollByPages) window.scrollByPages(-1);
return false;
}
if (ev.keyCode==34) { // PGDN
if (window.scrollByPages) window.scrollByPages(1);
return false;
}
if (e.savedkeypress) e.savedkeypress();
}
}
e.style.height=e.scrollHeight+'px';
if (e.button) e.button.innerHTML=config.commands.autosizeEditor.text_alt;
e.maxed=true;
},
off: function(e,resetHeight) {
if (resetHeight) e.style.height=e.savedheight;
e.onkeyup=e.savedkeyup;
// IE reports error: "not implemented" for onkeypress
if (!config.browser.isIE) e.onkeypress=e.savedkeypress;
if (e.button) e.button.innerHTML=config.commands.autosizeEditor.text;
e.maxed=false;
}
};
config.macros.autosizeEditor={
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var here=story.findContainingTiddler(place); if (!here) return;
var ta=here.getElementsByTagName('textarea'); if (!ta) return;
for (i=0;i<ta.length;i++) {
// only autosize textareas actually used to edit tiddler fields
if (ta[i].getAttribute("edit")==undefined) continue;
config.commands.autosizeEditor.on(ta[i]);
}
return false;
}
}
//}}}
// // grab-and-stretch handle
//{{{
config.macros.resizeEditor = { // add stretch bar to editor textarea
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var here=story.findContainingTiddler(place); if (!here) return;
var ta=here.getElementsByTagName('textarea');
if (ta) for (i=0;i<ta.length;i++) {
// only resize tiddler editor textareas
if (ta[i].getAttribute("edit")==undefined) continue;
new window.TextAreaResizer(ta[i]);
}
}
}
config.macros.resizeTiddler = { // add stretch bar to tiddler viewer element
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var here=story.findContainingTiddler(place); if (!here) return;
var elems=here.getElementsByTagName('div');
if (elems) for (i=0;i<elems.length;i++) if (hasClass(elems[i],'viewer')) break;
if (i<elems.length) new window.TextAreaResizer(elems[i]);
}
}
config.macros.resizeFrame = { // add stretch bar to iframes
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var here=story.findContainingTiddler(place); if (!here) return;
var fr=here.getElementsByTagName('iframe');
if (fr) for (i=0;i<fr.length;i++) new window.TextAreaResizer(fr[i]);
}
}
config.macros.resizeListbox = { // add stretch bar to listbox controls
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var here=story.findContainingTiddler(place); if (!here) here=place;
var fr=here.getElementsByTagName('select');
if (fr) for (i=0;i<fr.length;i++) new window.TextAreaResizer(fr[i]);
}
}
// TextAreaResizer script by Jason Johnston (jj@lojjic.net)
// Created August 2003. Use freely, but give me credit.
// adds a handle below textareas that the user can drag with the mouse to resize the textarea.
// MODIFIED by ELS for cross-browser (IE) compatibility, including:
window.TextAreaResizer = function(elt) {
this.element = elt;
this.create();
}
window.TextAreaResizer.prototype = {
create : function() {
var elt = this.element;
var thisRef = this;
var h = this.handle = document.createElement("div");
h.style.height = "2px"; // was 4px... looked too fat!
h.style.overflow = "hidden"; // ELS: force IE to trim height to < 1em
var adjust=elt.nodeName=='textarea'?4:0; // 4 pixels for textarea border edge
// h.style.width=(elt.offsetWidth-adjust)+"px";
h.style.width="auto";
h.style.backgroundColor = "#999"; // ELS: standard mid-tone (dark) gray
h.style.cursor = "s-resize";
h.title = "Drag to resize text box";
h.onmousedown=function(evt){thisRef.dragStart(evt)};
elt.parentNode.insertBefore(h, elt.nextSibling);
},
dragStart : function(evt) {
if (!evt) var evt=window.event;
this.dragStop(evt); // ELS: stop any current drag processing first
var thisRef = this;
this.dragStartY = evt.clientY;
this.dragStartH = this.element.offsetHeight;
document.savedmousemove=document.onmousemove;
document.onmousemove=this.dragMoveHdlr=function(evt){thisRef.dragMove(evt)};
document.savedmouseup=document.onmouseup;
document.onmouseup=this.dragStopHdlr=function(evt){thisRef.dragStop(evt)};
},
dragMove : function(evt) {
if (!evt) var evt=window.event;
// ELS: make sure height is at least 10px
var h=this.dragStartH+evt.clientY-this.dragStartY;
if (h<10) h=10; this.element.style.height=h+"px";
// ELS: match handle to textarea width (which may have changed due to document scrollbars)
// var adjust=this.element.nodeName.toLowerCase()=='textarea'?4:0; // 4 pixels for textarea
// this.handle.style.width=(this.element.offsetWidth-adjust)+"px";
// ELS: when manually resizing, disable autoresizing (without restoring saved height)
if (this.element.maxed!=undefined && this.element.maxed)
config.commands.autosizeEditor.off(this.element,false);
},
dragStop : function(evt) {
if (!evt) var evt=window.event;
document.onmousemove=(document.savedmousemove!=undefined)?document.savedmousemove:null;
document.onmousemove=(document.savedmouseup!=undefined)?document.savedmouseup:null;
},
destroy : function() {
var elt = this.element;
elt.parentNode.removeChild(this.handle);
elt.style.height = "";
}
};
//}}}
/***
|Name|TextAreaPluginInfo|
|Source|http://www.TiddlyTools.com/#TextAreaPlugin|
|Documentation|http://www.TiddlyTools.com/#TextAreaPluginInfo|
|Version|2.2.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for TextAreaPlugin|
Adds Find/Again keyboard search, autosize, and 'stretch bar' resize for textarea controls
!!!!!Usage
<<<
When in tiddler editor, use ''Control-F'' and ''control-G'' to ''"Find text"'' and ''"find text aGain"'', respectively, allowing you to copy, find, paste, findagain, paste, etc to perform "search-and-replace" actions. ''autosize'' toolbar command toggles the tiddler editor textarea height between fixed-height and "automatically fit the contents". Stretch (change height) of editor (or other element types) using 'grab handle' that is displayed below the editor textarea field.
<<<
!!!!!Configuration
<<<
<<option chkTextAreaExtensions>> use control-f (find), control-g (find again) inside text area
<<option chkDisableAutoSelect>> place cursor at start of textarea instead of pre-selecting content
<<option chkResizeEditor>> modify shadow EditTemplate to add resizeable text area (and autosize command)
* ''Add 'autosizeEditor' command to toolbar:''
{{{
// add command keyword to end of {{{EditToolbar}}} slice definition in [[ToolbarCommands]]:
|EditToolbar| ... autosizeEditor|
}}}
* Alternatively, ''enable autosize by default:''
{{{
// add to the end of the EditTemplate:
<span macro='autosizeEditor'></span>
}}}
* ''Add stretch bar to editor:''
{{{
// add ''resize...'' macro to EditTemplate
<span macro='resizeEditor'></span> or
<span macro='resizeTiddler'></span> or
<span macro='resizeFrame'></span> or
<span macro='resizeListbox'></span>
}}}
<<<
!!!!!Revisions
<<<
2009.04.06 [2.2.0] added resizeListbox macro definition and adjusted dragbar width calculation.
2008.01.08 [2.1.9] fixed default setting of uninitialized option values so that "false" is not treated as "undefined"
2008.01.07 [2.1.8] added 'initialized' flag so keyDownHandlers() will only be added once to each control (prevents recursion errors)
2007.12.21 [2.1.7] in dragMove(), subtract 4-pixel 'fudge factor' when adjusting drag bar width to match textarea width. Apparently textarea 'offsetWidth' includes the 2-pixel surrounding edge, but CSS 100% calculation does NOT, resulting is an increase in the textarea width when displayed in a variable-width moveable panel.
2007.11.19 [2.1.6] fix fatal IE errors by NOT setting 'onkeypress' handler (which IE reports as "not implemented"). Also, only add autosize grab bar to textareas that are actually used to edit tiddler fields (i.e., they have an "edit=fieldname" attribute). This prevents undesirable autosizing of textareas used for HTML/DOM display by [[PreviewPlugin]].
2007.11.18 [2.1.5] in config.commands.autosizeEditor, changed alt command text to use character-based "psuedo-checkbox" instead of embedded html fragment
2007.09.04 [2.1.4] in window.TextAreaResizer.prototype.create(), set initial grab handle width to auto instead of matching textarea.offsetWidth (which can be initially==0)
2007.04.29 [2.1.3] in addKeyDownHandlers(), used 'findText' instead of 'find', hopefully to avoid strict ECMAScript1.5 error on certain browsers.
2007.03.01 [2.1.2] use apply() to invoke hijacked core function
2006.11.16 [2.1.0] restored chkDisableAutoSelect (place cursor at start of textarea instead of pre-selecting content)
2006.11.16 [2.0.0] removed chkDisableEscapeKey (obsolete... use custom EditTemplate to change toolbar definition). Rewrote focusTiddler as a HIJACK instead of just overwriting core function (permits other plugins to also hijack function). Removed TAB character processing (now built-in as of TW2.1). Merged code from ResizeEditorPlugin:
> 2006.11.16 [1.3.x] merged with TextAreaPlugin
> 2006.11.02 [1.3.1] in DragMove() and DragStop(), check for undefined properties so IE doesn't report "Not Implemented" error when property is referenced without having been previously initialized.
> 2006.11.01 [1.3.0] added 'resizeEditor' MACRO for 'grab handle' stretch resizing (based on code from Jon Scully and Jason Johnston (jj@lojjic.net).
> 2006.11.01 [1.2.6] removed increaseEditor, decreaseEditor, and resizeEditor toolbar COMMAND definitions (resize by setting 'rows' property of textarea field conflicts with resize via style.height CSS attribute as set by autosize/drag).
> 2006.11.01 [1.2.5] fixed 'savedkeypress' handling (was writing to savedkeyup by mistake)
> 2006.10.28 [1.2.4] added '+' to 'saveTiddler' toolbar command (enables ctrl-enter keyhandling)
> 2006.10.18 [1.2.3] added decreaseEditor and increaseEditor commands
> 2006.10.18 [1.2.2] onkeypress handling to redirect PGUP/PGDN to window.scrollByPages() (works in FF, but not yet in IE)
> 2006.10.18 [1.2.1] fixed references to default string constants (oops!)
> 2006.10.18 [1.2.0] renamed 'resizeEditor' to 'autosizeEditor' and added new 'resizeEditor' toolbar command to prompt for # of rows to display
> 2006.10.02 [1.1.1] show checkbox in button label (when automatic resizing is enabled)
> 2006.10.01 [1.1.0] added 'onkeyup' automatic fit-to-contents handling
> 2006.09.30 [1.0.0] initial release
2006.08.01 [1.1.2] improved processed() utility function to handle IE5 and IE6, as well as calling preventDefault() for moz browsers. Thanks to Bradley Meck for research and code examples.
2006.07.09 [1.1.1] removed chkDisableAutoSelect
2006.02.14 [1.1.0] added option for chkDisableEscapeKey (default is standard action)
2006.01.22 [1.0.1] only add extra key processing for TEXTAREA elements (not other edit fields).
added option to enable/disable textarea keydown extensions (default is "standard keys" only)
2006.01.22 [1.0.0] Moved from temporary "System Tweaks" tiddler into 'real' TextAreaPlugin tiddler.
<<<
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demos
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], open several tiddlers to use the tabs bar.
!Installation
#import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
#save and reload
#''if you're using a custom [[PageTemplate]]'', add {{{<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>}}} before {{{<div id='tiddlerDisplay'></div>}}}
#optionally, adjust StyleSheetTiddlersBar
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed.
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab = config.options.chkHideTabsBarWhenSingleTab ? config.options.chkHideTabsBarWhenSingleTab : false;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
tooltip : "see ",
tooltipClose : "click here to close this tab",
tooltipSave : "click here to save this tab",
promptRename : "Enter tiddler new name",
currentTiddler : "",
previousState : false,
previousKey : config.options.txtPreviousTabKey,
nextKey : config.options.txtNextTabKey,
tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
handler: function(place,macroName,params) {
var previous = null;
if (config.macros.tiddlersBar.isShown())
story.forEachTiddler(function(title,e){
if (title==config.macros.tiddlersBar.currentTiddler){
var d = createTiddlyElement(null,"span",null,"tab tabSelected");
config.macros.tiddlersBar.createActiveTabButton(d,title);
if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
previous = "active";
}
else {
var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
btn.setAttribute("tiddler", title);
if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
previous=btn;
}
var isDirty =story.isDirty(title);
var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
c.setAttribute("tiddler", title);
if (place.childNodes) {
place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
place.insertBefore(d,place.firstChild);
}
else place.appendChild(d);
})
},
refresh: function(place,params){
removeChildren(place);
config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
story.refreshAllTiddlers();
if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
}
},
isShown : function(){
if (config.options.chkDisableTabsBar) return false;
if (!config.options.chkHideTabsBarWhenSingleTab) return true;
var cpt=0;
story.forEachTiddler(function(){cpt++});
return (cpt>1);
},
selectNextTab : function(){ //used when the current tab is closed (to select another tab)
var previous="";
story.forEachTiddler(function(title){
if (!config.macros.tiddlersBar.currentTiddler) {
story.displayTiddler(null,title);
return;
}
if (title==config.macros.tiddlersBar.currentTiddler) {
if (previous) {
story.displayTiddler(null,previous);
return;
}
else config.macros.tiddlersBar.currentTiddler=""; // so next tab will be selected
}
else previous=title;
});
},
onSelectTab : function(e){
var t = this.getAttribute("tiddler");
if (t) story.displayTiddler(null,t);
return false;
},
onTabClose : function(e){
var t = this.getAttribute("tiddler");
if (t) {
if(story.hasChanges(t) && !readOnly) {
if(!confirm(config.commands.cancelTiddler.warning.format([t])))
return false;
}
story.closeTiddler(t);
}
return false;
},
onTabSave : function(e) {
var t = this.getAttribute("tiddler");
if (!e) e=window.event;
if (t) config.commands.saveTiddler.handler(e,null,t);
return false;
},
onSelectedTabButtonClick : function(event,src,title) {
var t = this.getAttribute("tiddler");
if (!event) event=window.event;
if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
return false;
},
onTiddlersBarAction: function(event) {
var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
},
createActiveTabButton : function(place,title) {
if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
btn.setAttribute("tiddler", title);
}
else
createTiddlyText(place,title);
}
}
story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;
story.closeTiddler = function(title,animate,unused) {
if (title==config.macros.tiddlersBar.currentTiddler)
config.macros.tiddlersBar.selectNextTab();
story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
var e=document.getElementById("tiddlersBar");
if (e) config.macros.tiddlersBar.refresh(e,null);
}
story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;
if (config.macros.tiddlersBar.isShown()) {
story.forEachTiddler(function(t,e){
if (t!=title) e.style.display="none";
else e.style.display="";
})
config.macros.tiddlersBar.currentTiddler=title;
}
var e=document.getElementById("tiddlersBar");
if (e) config.macros.tiddlersBar.refresh(e,null);
}
var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
coreRefreshPageTemplate(title);
if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}
ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)
config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);
config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");
//}}}
/%
|Name|ToggleRightSidebar|
|Source|http://www.TiddlyTools.com/#ToggleRightSidebar|
|Version|2.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|show/hide right sidebar (MainMenu)|
Usage: <<tiddler ToggleRightSidebar with: "label">>
Config settings:
config.options.chkShowRightSidebar (true)
config.options.txtToggleRightSideBarLabelShow (◄)
config.options.txtToggleRightSideBarLabelHide (►)
%/<script label="$1" title="show/hide right sidebar content">
var co=config.options;
if (co.chkShowRightSidebar=='undefined') co.chkShowRightSidebar=true;
co.chkShowRightSidebar=!co.chkShowRightSidebar;
var sb=document.getElementById('sidebar'); if (!sb) return;
sb.style.display=co.chkShowRightSidebar?'block':'none';
document.getElementById('displayArea').style.marginRight=co.chkShowRightSidebar?'':'1em';
saveOptionCookie('chkShowRightSidebar');
var labelShow=co.txtToggleRightSideBarLabelShow||'◄';
var labelHide=co.txtToggleRightSideBarLabelHide||'►';
if (typeof(place)!='undefined' && '$1'=='$'+'1') {
place.innerHTML=co.chkShowRightSidebar?labelHide:labelShow;
place.title=(co.chkShowRightSidebar?'hide':'show')+' right sidebar';
}
var sm=document.getElementById('storyMenu'); if (sm) config.refreshers.content(sm);
</script><script>
var co=config.options;
if (co.chkShowRightSidebar=='undefined') co.chkShowRightSidebar=true;
var sb=document.getElementById('sidebar'); if (!sb) return;
sb.style.display=co.chkShowRightSidebar?'block':'none';
document.getElementById('displayArea').style.marginRight=co.chkShowRightSidebar?'':'1em';
if ('$1'=='$'+'1') {
var labelShow=co.txtToggleRightSideBarLabelShow||'◄';
var labelHide=co.txtToggleRightSideBarLabelHide||'►';
place.lastChild.innerHTML=co.chkShowRightSidebar?labelHide:labelShow;
place.lastChild.title=(co.chkShowRightSidebar?'hide':'show')+' right sidebar';
}
</script>
|~ViewToolbar|closeTiddler closeOthers closeAll +editTiddler > publishTiddler fields syncing permalink references jump|
|~EditToolbar|+saveTiddler saveCloseTiddler -cancelTiddler cancelCloseTiddler deleteTiddler|
|~EditRecordToolbar|+saveTiddlerCascade -cancelTiddler deleteTiddlerCascade|
[[Help]] [[View Classes]] [[View Students]] <<newTiddler label:"Add Class" text:"" tag:"Class" title:"NewClass" template:"ClassEditTemplate">> <<newTiddler tag:"Student" label:"Add Student" text:"" template:"StudentEditTemplate" >> <<search>> <<refreshDisplay>> [[RecentChanges]] <<saveChanges>> <<unsavedChanges command>>
/***
|Name:|TrashPlugin|
|Version:|1.2.0|
|Source:|http://www.TiddlyTools.com/#TrashPlugin|
|Author:|Eric Shulman|
|OriginalSource:|http://ido-xp.tiddlyspot.com/#TrashPlugin|
|OriginalAuthor:|Ido Magal (idoXatXidomagalXdotXcom)|
|License:|[[BSD open source license]]|
|CoreVersion:|2.1.0|
|Description|add 'Trash' tag to tiddlers instead of deleting them|
!!!!!Documentation
<<<
When TrashPlugin is installed and you click on the 'delete' command in the tiddler toolbar, rather than directly removing the tiddler from the system, it will be tagged with the following tags:
{{{
Trash excludeLists excludeMissing excludeSearch systemConfigDisable
}}}
As a result, although the tiddler still exists within the document, it is ''hidden from view and will not be searched or invoked as a plugin.''
*{{block{
To view a list of all tiddlers tagged with {{{Trash}}}, simply open the [[Trash]] tiddler (aka, the "trash can").}}}
*{{block{
To reclaim a tiddler from the [[Trash]], click on a title in the trash can to open that tiddler. Then, edit it to remove the Trash tag (as well as the other tags noted above).}}}
*{{block{
To empty the trash can (i.e. actually //delete// the tiddlers), click on the ''//"empty trash"//'' button that appears in the [[Trash]] tiddler. You can also add this button to your [[SideBarOptions]] or any other desired location by using the following macro:
{{{
<<emptyTrash>>
}}}
}}}
*{{block{
To ''bypass the trash can'' and use the normal delete handling (with the usual confirmation messages, if chkConfirmDelete is enabled), hold CTRL while clicking 'delete'}}}
*{{block{
To ''bypass both the trash can //and// the confirmation message'' and //immediately delete// the tiddler without any further interaction, hold CTRL+SHIFT while clicking 'delete'}}}
<<<
!!!!!Revisions
<<<
2009.05.20 [1.2.0] documentation rewrite and code cleanup/reduction
2009.05.12 [1.1.0.5] refactored code to add entry point: {{{config.commands.deleteTiddler.sendToTrash(title)}}}
2008.11.14 [1.1.0.4] added SHIFT-CLICK = bypass trash and delete immediately WITHOUT CONFIRMATION
2008.10.14 [1.1.0.3] return FALSE from emptyTrash() handler (fixes IE page transition error)
2008.05.18 [1.1.0.2] when creating the Trash tiddler, pass an empty tags array [] instead of a null value, so other plugins (e.g., InstantTimestampPlugin) won't fail
2006.12.21 [1.1.0.1] only call setDirty() when actually removing tiddlers from trash
2006.12.12 [1.1.0.0] added movedMsg (feedback when tiddler is tagged as Trash). Make sure tiddler actually exists before tagging it with 'Trash'. Fetch correct tiddler before checking for 'systemConfig' tag
2006.12.11 [1.0.3.1] Don't create Trash tiddler until needed. Remove Trash tiddler when no trash remains. Don't tag Trash tiddler with 'TrashPlugin'. Moved all user-visible strings to variables so they can be translated by 'lingo' plugins. Use displayMessage() instead of alert()
2006.12.11 [1.0.3] Fixed broken reference to core deleteTiddler. Now storing reference to core deleteTiddler in emptyTrash macro. Reduced deleteTiddler hijacking to only the handler.
2006.12.11 [1.0.2] EmptyTrash now uses removeTiddler instead of deleteTiddler. Supports trashing systemConfig tiddlers (adds systemConfigDisable tag).
2006.12.10 [1.0.1] Replaced TW version with proper Core reference. Now properly hijacking deleteTiddler command.
2006.12.10 [1.0.0] First draft.
<<<
!!!!!Code
***/
//{{{
version.extensions.TrashPlugin= {major: 1, minor: 2, revision: 0, date: new Date(2009,5,20)};
//}}}
//{{{
config.macros.emptyTrash = {
tag: 'Trash',
movedMsg: "'%0' has been tagged as %1",
label: 'empty trash',
tooltip: 'Delete all items tagged as %0',
tooltipOlder: 'Delete items tagged as %0 that are older than %1 days old',
emptyMsg: 'The trash is empty',
noneToDeleteMsg: 'There are no items in the trash older than %0 days',
confirmMsg: "The following tiddlers will be deleted:\n\n'%0'\n\nOK to proceed?",
deletedMsg: "Deleted '%0'",
handler: function ( place,macroName,params,wikifier,paramString,tiddler ) {
var namedParams = (paramString.parseParams(daysOld))[0];
var daysOld = namedParams['daysOld'] ? namedParams['daysOld'][0] : 0; // default
var buttonTitle = namedParams['title'] ? namedParams['title'][0] : this.label;
var buttonTip=this.tooltip.format([this.tag])
if (daysOld) buttonTip=this.tooltipOlder.format([this.tag,daysOld])
var b=createTiddlyButton(place,buttonTitle,buttonTip,this.emptyTrash);
b.setAttribute('daysOld',daysOld);
},
emptyTrash: function() {
var cme=config.macros.emptyTrash; // abbrev
var daysOld=this.getAttribute('daysOld');
var compareDate=new Date(); compareDate.setDate(compareDate.getDate()-daysOld);
var collected=[];
store.forEachTiddler(function(title,tiddler) {
if (tiddler.isTagged(cme.tag) && tiddler.modified<compareDate)
collected.push(title);
});
if (!collected.length)
displayMessage(daysOld ? cme.noneToDeleteMsg.format([daysOld]) : cme.emptyMsg);
else if (confirm(cme.confirmMsg.format([collected.join("', '")]))) {
for (var i=0;i<collected.length;i++) {
store.removeTiddler(collected[i]);
store.setDirty(true);
displayMessage(cme.deletedMsg.format([collected[i]]));
}
}
if (!store.getTaggedTiddlers(cme.tag).length) // remove Trash if empty
{ story.closeTiddler(cme.tag,true,false); store.removeTiddler(cme.tag); }
else
story.refreshTiddler(cme.tag,false,true); // refresh Trash if visible
return false;
}
}
//}}}
// // hijack delete command
//{{{
config.commands.deleteTiddler.orig_handler=config.commands.deleteTiddler.handler;
config.commands.deleteTiddler.handler=function(event,src,title) {
// BYPASS TRASH: CTRL=normal delete, CTRL+SHIFT=without confirmation
if (event.ctrlKey) {
if (event.shiftKey) { var temp=config.options.chkConfirmDelete; config.options.chkConfirmDelete=false; }
config.commands.deleteTiddler.orig_handler.apply(this,arguments);
if (event.shiftKey) config.options.chkConfirmDelete=temp;
story.refreshTiddler(config.macros.emptyTrash.tag,false,true);
return false;
}
config.commands.deleteTiddler.sendToTrash(title);
return false;
};
config.commands.deleteTiddler.sendToTrash = function(title) {
var cme=config.macros.emptyTrash; // abbrev
if (!store.tiddlerExists(title)) return; // make sure tiddler actually exists
if (!store.tiddlerExists(cme.tag)) // make sure Trash tiddler exists
store.saveTiddler(cme.tag,cme.tag,'<<emptyTrash>>','TrashPlugin',new Date(),[],{});
store.setTiddlerTag(title,1,cme.tag);
store.setTiddlerTag(title,1,'excludeLists');
store.setTiddlerTag(title,1,'excludeMissing');
store.setTiddlerTag(title,1,'excludeSearch');
if (store.getTiddler(title).isTagged('systemConfig'))
store.setTiddlerTag(title,1,'systemConfigDisable');
story.closeTiddler(title,true);
if(config.options.chkAutoSave) saveChanges();
displayMessage(cme.movedMsg.format([title,cme.tag]));
story.refreshTiddler(cme.tag,false,true);
};
//}}}
/***
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 = 'classrecords';
// 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,{
'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"),
'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"),
'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"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
<<upload http://classrecords.tiddlyspot.com/store.cgi index.html . . classrecords>><html><a href='http://classrecords.tiddlyspot.com/download' class='button'>download</a></html>
<<unsavedChanges command>>
/***
|Name|UnsavedChangesPlugin|
|Source|http://www.TiddlyTools.com/#UnsavedChangesPlugin|
|Version|3.3.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|TiddlyWiki.prototype.setDirty,store.saveTiddler,store.removeTiddler|
|Description|show droplist of tiddlers that have changed since the last time the document was saved|
Display a list of tiddlers that have been changed since the last time the document was saved. The list includes all new/modified tiddlers as well as those changed with "minor edits" enabled and any tiddlers that you import during the session, regardless of their modification date.
!!!!!Usage
<<<
{{{
<<unsavedChanges panel>> or <<unsavedChanges>>
}}}
{{indent{
the ''panel'' keyword displays a 'control panel' interface containing a droplist of unsaved tiddlers and a 'goto' button, along with a command link to 'save changes'. Depending upon what other plugins are installed, several additional elements will also be displayed: When [[NestedSlidersPlugin]] is installed, the entire control panel is contained within a ''SLIDER''. When [[LoadTiddlersPlugin]] is installed, a ''REVERT'' button is added. When [[SaveAsPlugin]] is installed, a ''SAVE AS'' link is added. When [[UploadPlugin]] is installed, an ''UPLOAD'' (or ''save to web'') link is added. When [[TrashPlugin]] is installed and there are tiddlers tagged with<<tag Trash>>, an ''EMPTY TRASH'' link is added.
}}}
{{{
<<unsavedChanges list separator>>
}}}
{{indent{
the ''list'' keyword displays a simple space-separated list of unsaved tiddlers without any other command links. You can specify an optional ''separator'' value that can be used in place of the default space character. For example, you can specify {{{"<br>"}}} as the separator in order to display each link, one per line.
}}}
{{{
<<unsavedChanges command label tip>>
}}}
{{indent{
the ''command'' keyword displays a single 'command link' that, when clicked, displays a ~TiddlyWiki popup containing the list of unsaved tiddlers, the 'save changes' command and, depending upon what other plugins are installed, additional commands for 'save as', 'upload', and 'empty trash' (similar to the panel display described above).
You can specify optional ''label'' and ''tip'' parameters in the macro to customize the command link text and tooltip. The default label for the command link is: "There %1 %0 unsaved tiddler%2...", where:
* %0 is automatically replaced with the number of unsaved changes
* %1 is either "is" (if changes=1) or "are" (if changes>1)
* %2 is either blank (if changes=1) or "s" (if changes>1)
resulting in the text: //"There is 1 unsaved tiddler...", "There are 2 unsaved tiddlers...", etc.//
}}}
<<<
!!!!!Examples
<<<
^^//note: the following examples will not display any output unless you have already created/modified tiddlers in the current document.//^^
{{{<<unsavedChanges>>}}}
<<unsavedChanges>>
----
{{{<<unsavedChanges command>>}}}
<<unsavedChanges command>>
----
{{{<<unsavedChanges list>>}}}
<<unsavedChanges list>>
----
{{{<<unsavedChanges list "<br>">>}}}
<<unsavedChanges list "<br>">>
<<<
!!!!!Revisions
<<<
2009.03.02 [3.3.3] fix handling for titles that contain HTML special chars (lt,gt,quot,amp)
2008.09.02 [3.3.2] cleanup popup list output generation and added timestamps/sizes to popup display
2008.08.23 [3.3.1] added optional custom 'label' and 'tip' params to 'command' mode and defined default values for mode, label, tip, and separator as object properties for I18N/L10N-readiness.
2008.08.21 [3.3.0] complete re-write of rendering and refresh processing to support multiple instances and automatic self-refresh (no longer depends upon core refresh notifications)
2008.08.21 [3.2.0] added 'command' option for link+popup as alternative to 'control panel' interface
2008.04.22 [3.1.2] use SaveAsPlugin instead of obsolete NewDocumentPlugin to add "save as" link
2007.12.22 [3.1.1] hijack removeTiddler() instead of low-level deleteTiddler() to correct tracking and refresh handling issues. in saveTiddler(), check for 'tiddler rename' (title!=newtitle) and adjust list accordingly.
2007.12.21 [3.1.0] added support for {{{<<unsavedChanges list separator>>}}} usage to unsaved tiddlers as a simple list of links, embedded in tiddler content (e.g., [[MainMenu]])
2007.12.20 [3.0.0] rewrite to track ALL changed tiddlers, including imports and minor edits, regardless of saved modification dates. Also, rewrote display logic to directly refresh macro output instead of triggering a page refresh. The entire process is MUCH more efficient now.
2007.08.02 [2.0.0] converted from inline script
2007.01.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.UnsavedChangesPlugin= {major: 3, minor: 3, revision: 3, date: new Date(2009,3,2)};
config.macros.unsavedChanges = {
changed: [], // list of currently unsaved tiddler titles
defMode: "panel",
defSep: " ",
defLabel: "There %1 %0 unsaved tiddler%2...",
defTip: "view a list of unsaved tiddler changes",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var wrapper=createTiddlyElement(place,"span",null,"unsavedChanges");
wrapper.setAttribute("mode",params[0]||this.defMode);
wrapper.setAttribute("sep",params[1]||this.defSep); // for 'list' mode
wrapper.setAttribute("label",params[1]||this.defLabel); // for 'command' mode
wrapper.setAttribute("tip",params[2]||this.defTip); // for 'command' mode
this.render(wrapper);
},
render: function(wrapper) {
removeChildren(wrapper); // make sure its empty
if (!this.changed.length) return; // no changes = no output
switch (wrapper.getAttribute("mode")) {
case "command": this.command(wrapper); break;
case "list": this.list(wrapper); break;
case "panel": default: this.panel(wrapper); break;
}
},
refresh: function() {
var wrappers=document.getElementsByTagName("span");
for (var w=0; w<wrappers.length; w++)
if (hasClass(wrappers[w],"unsavedChanges"))
this.render(wrappers[w]);
},
list: function(place) { // show simple list of unsaved tiddlers
wikify("[["+this.changed.join("]]"+place.getAttribute("sep")+"[[")+"]]",place);
},
command: function(place) { // show command link with popup list
var c=this.changed.length;
var txt=place.getAttribute("label").format([c,c==1?'is':'are',c==1?'':'s']);
var tip=place.getAttribute("tip");
var action=function(ev) { if (!ev) var ev=window.event;
var p=Popup.create(this); if (!p) return false;
var d=createTiddlyElement(p,"div");
d.style.whiteSpace="normal"; d.style.width="auto"; d.style.padding="2px";
// gather pretty links for changed tiddlers
var list=[]; var item=" [[%1 - %0 (%2 bytes)|%0]] ";
for (var i=config.macros.unsavedChanges.changed.length-1; i>=0; i--) {
var tid=store.getTiddler(config.macros.unsavedChanges.changed[i]);
if (!tid) continue;
var when=tid.modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
list.push(item.format([tid.title,when,tid.text.length]));
}
wikify("@@white-space:nowrap;"+list.join("<br>")+"@@",d);
if (!readOnly) {
var t="\n----\n";
t+="@@white-space:nowrap;display:block;text-align:center; ";
t+="<<saveChanges>>";
t+=config.macros.saveAs?" | <<saveAs>>":"";
t+=config.macros.upload?" | <<upload>>":"";
t+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
t+=" @@";
wikify(t,d);
}
Popup.show();
ev.cancelBubble=true; if(ev.stopPropagation)ev.stopPropagation();
return(false);
}
createTiddlyButton(place,txt,tip,action,"button");
},
panel: function(place) { // show composite droplist+buttons+commands
// gather changed tiddlers (in reverse order by date - most recent first)
var tids=[]; for (var i=this.changed.length-1; i>=0; i--)
{ var t=store.getTiddler(this.changed[i]); if (t) tids.push(t); }
tids.sort(function(a,b){return a.modified<b.modified?-1:(a.modified==b.modified?0:1);});
// generate droplist items
var list=[]; var item='<option value="%0">%1 - %0 (%2 bytes)</option>';
for (var i=tids.length-1; i>=0; i--) {
var when=tids[i].modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
list.push(item.format([tids[i].title.htmlEncode(),when,tids[i].text.length]));
}
// display droplist, buttons, and command links
var out=''; var c=this.changed.length;
var NSP=config.formatters.findByField("name","nestedSliders");
var summary=this.defLabel.format([c,c==1?'is':'are',c==1?'':'s'])
out+=NSP?'+++(unsaved)['+summary+'|'+this.defTip+']...':(summary+"\n");
out+='<html><form style="display:inline"><!--\
--><select size="1" name="list" \
title="select a tiddler to view" \
onchange="var v=this.value; if (v.length) story.displayTiddler(null,v);"><!--\
-->'+list.join('')+'<!--\
--></select><!--\
--><input type="button" value="goto" onclick="this.form.list.onchange();">';
if (config.macros.loadTiddlers) {
out+='<input type="button" value="revert" \
title="import the last saved version of this tiddler" \
onclick="var v=this.form.list.value; if (!v.length) return; \
var t=\'<\'+\'<loadTiddlers [[tiddler:\'+v+\']] \'; \
t+=document.location.href; \
t+=\' confirm force noreport>\'+\'>\'; \
var e=document.getElementById(\'executeRevert\'); \
if (e) e.parentNode.removeChild(e); \
e=document.createElement(\'span\'); \
e.id=\'executeRevert\'; \
wikify(t,e);">';
}
out+='</form></html>';
if (!readOnly) {
out+='\n{{small nowrap{';
out+="<<saveChanges>>";
out+=config.macros.saveAs?" | <<saveAs>>":"";
out+=config.macros.upload?" | <<upload>>":"";
out+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
out+='}}}';
}
out+=NSP?'===':'';
wikify(out,place);
}
};
// hijack store.saveTiddler() to track changes to tiddlers
if (store.showUnsaved_saveTiddler==undefined) {
store.showUnsaved_saveTiddler=store.saveTiddler;
store.saveTiddler=function(title,newtitle) {
if (title!=newtitle) {
var i=config.macros.unsavedChanges.changed.indexOf(title);
if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove old from list
}
var i=config.macros.unsavedChanges.changed.indexOf(newtitle);
if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove new title from list
config.macros.unsavedChanges.changed.push(newtitle); // add new title to END of list
var t=this.showUnsaved_saveTiddler.apply(this,arguments);
if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
return t;
}
}
// hijack store.removeTiddler() to track changes to tiddlers
if (store.showUnsaved_removeTiddler==undefined) {
store.showUnsaved_removeTiddler=store.removeTiddler;
store.removeTiddler=function(title) {
var i=config.macros.unsavedChanges.changed.indexOf(title);
if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove from list
this.showUnsaved_removeTiddler.apply(this,arguments);
if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
}
}
// hijack store.setDirty() function to reset change list after file save
// note: do NOT hijack the prototype function. This hijack should only be applied to
// the main 'store' instance only (i.e., don't refresh when loading temporary store
// as part of ImportTiddlers processing)
if (store.showUnsaved_setDirty==undefined) {
store.showUnsaved_setDirty=store.setDirty;
store.setDirty = function(flag) {
var refresh=this.isDirty() && !flag; // 'dirty' to 'clean', force a refresh...
this.showUnsaved_setDirty.apply(this,arguments); // but change the flag first.
if (refresh) {
config.macros.unsavedChanges.changed=[]; // clear changed list
config.macros.unsavedChanges.refresh();
}
}
}
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 03/09/2009 08:47:11 | ShavinderPalSingh | [[classrecords2.html|file:///home/shavinder/Desktop/active-tws/classrecords2.html]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 03/09/2009 08:51:15 | ShavinderPalSingh | [[classrecords2.html|file:///home/shavinder/Desktop/active-tws/classrecords2.html]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . |
| 15/09/2009 20:50:28 | YourName | [[/|http://classrecords.tiddlyspot.com/]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 15/09/2009 21:14:12 | YourName | [[/|http://classrecords.tiddlyspot.com/]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . |
| 15/09/2009 21:54:01 | YourName | [[/|http://classrecords.tiddlyspot.com/]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 15/09/2009 22:55:29 | YourName | [[/|http://classrecords.tiddlyspot.com/]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 15/09/2009 23:00:22 | YourName | [[/|http://classrecords.tiddlyspot.com/]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . |
| 15/10/2009 18:39:20 | Shavinder | [[classrecords.html|file:///root/my-documents/TWs/classrecords.html]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 15/10/2009 18:44:21 | Shavinder | [[classrecords.html|file:///root/my-documents/TWs/classrecords.html]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.tiddlyspot.com/index.html]] | . | ok |
| 03/03/2010 19:02:13 | Shavinder | [[classrecords.html|file:///root/my-documents/TWs/classrecords.html]] | [[store.cgi|http://classrecords.tiddlyspot.com/store.cgi]] | . | [[index.html | http://classrecords.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");
//}}}
<<tiddler ClassRecordsStyleSheet>>
<script>
var years={};
var classes=store.getTaggedTiddlers('Class');
var enrolled = 0;
for (var c=0; c<classes.length; c++) {
var y=classes[c].fields.year;
if (years[y]===undefined) years[y]=[];
years[y].push(classes[c]);
}
var out=[];
for (var y in years) {
out.push('!'+y);
out.push('(click on column header to sort but before this click on refresh once)');
out.push('|sortable|k');
out.push('|Class Id|Started on|h');
for (var c=0; c<years[y].length; c++){
out.push('|[['+years[y][c].title+']]|'+years[y][c].fields.date+'/'+years[y][c].fields.month+'/'+years[y][c].fields.year+'|');
//out.push('*[['+years[y][c].title+']]');
}
out.push('!end');
}
var shadowTiddler = 'AllClasses';
config.shadowTiddlers[shadowTiddler]=out.join('\n');
var out=[];
for (var y in years){
out.push('[['+y+']] [['+y+']] [['+shadowTiddler+'##'+y+']]');
}
var heading = 'There are '+classes.length+' classes in '+out.length+' years';
return heading+'<<tabs txtStudentTabs '+out.join(' ')+'>>';
</script>
<<tiddler ClassRecordsStyleSheet>>
<script>
var years={};
var students=store.getTaggedTiddlers('Student');
for (var s=0; s<students.length; s++) {
var y=students[s].fields.year_admission;
if (years[y]===undefined) years[y]=[];
years[y].push(students[s]);
}
var out=[];
for (var y in years) {
out.push('!'+y);
out.push('(click on column header to sort but before this click on refresh once)');
out.push('|sortable|k');
out.push('|Student Id|Name|Date of Admission|Email|Phone|Address|h');
for (var s=0; s<years[y].length; s++){
out.push('|[['+years[y][s].title+']]|'+years[y][s].fields.student_name+'|'+years[y][s].fields.date_admission+'/'+years[y][s].fields.month_admission+'/'+years[y][s].fields.year_admission+'|'+years[y][s].fields.email+'|'+years[y][s].fields.phones+'|'+years[y][s].fields.address+'|' );
//out.push('*[['+years[y][s].title+']]');
}
out.push('!end');
}
var shadowTiddler = 'AllStudents';
config.shadowTiddlers[shadowTiddler]=out.join('\n');
var out=[];
for (var y in years){
out.push('[['+y+']] [['+y+']] [['+shadowTiddler+'##'+y+']]');
}
var heading = 'There are '+students.length+' students in '+out.length+' years.';
return heading+'<<tabs txtStudentTabs '+out.join(' ')+'>>';
</script>
<script>
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
var classTiddler=store.getTiddler(tid);
var numDays=31; //assume for now
var students={};
var out=[];
for(field in classTiddler.fields){
if(field.indexOf("day")!=-1){
var SID=field.substring(0, field.indexOf("day"));
if(students[SID]===undefined) students[SID]=[];
}
}
for(s in students){
for(var i=1;i<=numDays;i++){
var fld=s+"day"+i;
students[s].push(classTiddler.fields[fld]);
}
}
var row=[];
row.push("|!SID");
for(var i=1;i<=numDays;i++){
row.push("|!"+i);
}
row.push("|!Total|!Shortage|");
out.push(row.join(""));
for(s in students){
var row=[];
row.push("|[["+s+"]]");
for(var i=0;i<numDays;i++){
row.push("|"+students[s][i]);
}
row.push("|<<tiddler CountAttendance>>");
row.push('|<<tiddler DifferenceInAttendance>>|');
out.push(row.join(""));
}
wikify(out.join('\n'), place);
</script>
<script>
var testTiddler= store.getTiddler(story.findContainingTiddler(place).getAttribute("tiddler"));
var students = {};
var out = [];
if(testTiddler.fields){
for(field in testTiddler.fields){
if(field.match(/^marks|^grade/)!=null){
var SID = field.slice(field.match(/^marks|^grade/)[0].toString().length);
if(students[SID]===undefined){
students[SID]=[];
}
if(field.match(/^marks/)!=null){
students[SID][0]=testTiddler.fields[field];
if(testTiddler.fields[field]>=testTiddler.fields.pass_marks)
students[SID][1]="Pass";
else
students[SID][1]="Fail";
}
else{
if(field.match(/^grade/)!=null)
students[SID][2]=testTiddler.fields[field];
}
}
}
}
out.push('|!~StudentId|!Marks|!Percentage|!Result|!Grade|');
for(var s in students){
out.push('|[['+s+']]|'+students[s][0]+'|'+(students[s][0]/testTiddler.fields.max_marks*100)+'|'+students[s][1]+'|'+students[s][2]+'|');
}
wikify(out.join('\n'),place);
</script>
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'>
<span class='toolbar' macro='toolbar snapshotPrint'></span>
<span class='toolbar' macro='tiddler RefreshTiddler'></span>
</div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<script>
var out=[];
for(var i=1960;i<=2050;i++)
out.push(i);
return(out.join("\n"));
</script>
<script>
var out=[];
for(var i=1960;i<2050;i++)
out.push(i);
return out.join('\n');
</script>
config.options.chkShowRightSidebar = false;
config.options.chkAutoSave = true;