Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
The first step in the GTD process is collecting all your tasks and projects. Get it on paper or in your ~TiddlyDu3 [[Inbox]] so that it's not on your mind.
!Possible sources for collecting tasks
*Scan your computer desktop, files
*Scan your home, office, files, etc.
*Review your e-mail inbox and folders
*Scan your browser bookmarks
*Ask your family, co-workers
*Review your calendar/agenda
*Review your goals, brainstorm for new ideas
<<reminder day:14 month:2 year:2009 title:"Buy Valentines Cards" >>
<<reminder day:15 month:3 year:2009 title:"Ides of March" >>
Use the following method to process to-do list items:
!Q: Is it actionable?
{{indent{''A: No - there are four possibilities:''
{{indent{{{indent{It's ''trash''
{{indent{{{indent{{{indent{ - delete it or throw it away.
{{indent{{{indent{It's a ''someday/maybe idea''
{{indent{{{indent{{{indent{ - create a task with Someday/maybe as its status
{{indent{{{indent{It's ''reference material''
{{indent{{{indent{{{indent{ - add it to the Info tab
{{indent{{{indent{It's an action ''waiting'' for something else to happen first
{{indent{{{indent{{{indent{ - create a task with Waiting as its status
{{indent{''A: Yes - it is one action that can be done in under 2 min.''}}}
{{indent{{{indent{{{indent{ Just do it, now, without processing it
{{indent{''A: Yes - one action that will take over 2 min. Three options:''}}}
{{indent{{{indent{Defer it to someone else
{{indent{{{indent{Add it to your calendar or create an appointment in the Calendars tab}}}}}}
{{indent{{{indent{Create a new task in the Tasks tab to do during the 'Do' step
{{indent{''A: Yes - but more than one action is necessary''}}}
{{indent{{{indent{Any action that is more than one step is a project
{{indent{{{indent{Create a new project in the Tasks tab
{{indent{{{indent{Don't forget to identify the next physical action to be taken for this project
Incremental change notes for those experimenting with TiddlyDu3:
1. I made a small change to Welcome, so that there is a link to the
help tiddlers. If you want to have this, import Welcome from
TiddlyDu3.
2. I added a help tiddler called Calendars and Appointments to
TabHelp. So if you want that, import both tiddlers.
3. I corrected the Acknowledgements & license tiddler, so if that's
important to you, make sure to get it.
I don't plan to have to do this indefinitely, so don't worry about a
constant string of daily updates from me. I just noticed that I had no
help tiddler for the Calendars tab, and took advantage to make the
other changes too. If I can make TiddlyDu3 better at the outset from
input from people here, everyone wins.
Dave
How embarrassing. In showing TiddlyDu3 to someone here, I discovered
that the ContactgroupViewTemplate didn't work. I had newTiddler
instead of newHere in the macro. So unfortunately that is one more
tiddler to import. Now you see why I ask you to test things out here.
Sorry about that!
Dave
Thanks Dave mine's fixed.
Something even more important is the sub menus in the tabs for
creating new goals, tasks contacts etc. on Tiddlydu3 seems to be
missing on the latest version.
I'll discuss the philosophy re: goals and projects later when I have
time :-) In His infinite wisdom we were all made different for a
reason - trouble is it's up to us to find out why:-)
Morris
If you created your new task tiddlers in the process stage and used the dropdown lists to indicate their status and tasktype, then you have already done the organizing step - congratulations!
The purpose of the weekly review is to continue the collecting, processing and organizing steps on a regular basis. David Allen recommends reviewing the following items to plan for the following week.
*Data left over from previous calendar dates
*Your calendars and your upcoming [[appointments|This week's appointments]]
*Your [[projects|TabProjects]]
*Your [[list of next actions|TabTasks]]
*Your [[waiting|Waiting]] list
*Any checklists in [[your Info tab|TabInfo]] that you've created to remind yourself of things
*Your [[someday - maybe ideas|Someday/Maybe]]
*Your [[reference materials|TabInfo]]
*Anything bouncing around in your head
*Be creative and dream of new ideas
Of course, all the other GTD steps are for the purpose of getting to this one. Do the tasks that you have set for yourself!
#Check your [[appointments|This week's appointments]] or physical agenda for date-specific tasks
#Check the [[Current]] tiddler for current tasks
<<siteMap [[A Task]] . sliders>>
Type the text for 'New Tiddler'
<<siteMap [[A subTopic]] . sliders>>
It's my privilege to be able to offer this resource for free. This is possible due to the efforts of various people:
*Jeremy Ruston, the creator of ~TiddlyWiki. ^^ TiddlyWiki <<version>> © 2008 [[UnaMesa|http://www.unamesa.org/]]^^
*The creators of the various piugins used in this adaptation of ~TiddlyWiki. Use the following button to see a list of the plugins used here. Each plugin contains information about its creator. <<tag systemConfig>>
*Morris Gray, who came up with the ~TiddlerBar idea, and various other helpful tweaks.
**TW ~TuDu is a customization of [[TiddlyDu3|http://www.giffmex.org/tiddlydu3.html]] by Morris Gray
**You can check the the version of all plugins [[here|PluginIdentifier]]
-----
^^<html><a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/88x31.png" /></a><br />{{{TiddlyDu3}}} is licensed by Dave Gifford under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a></html>^^
Use the button below to schedule appointments. Appointments created here will be added below. They will be also be visible in [[This week's appointments]] and [[All appointments]], and the date for the appointment will be highlighted light blue in the calendar found in the Calendar tab.
{{indent{<<addActivity '*Add a new appointment*'>>
You can also schedule date-specific appointments by clicking on a date in the calendar.
!List of appointments created here
<<reminder year:2009 month:2 day:14 title:"09:00-10:00 Lunch w/Nicole Kiddman" >>
<<reminder year:2009 month:2 day:11 title:"09:00-09:00 Buy Valentines Cards" hidden >>
<<reminder year:2009 month:2 day:13 title:"09:00-09:30 Climb Mt. Everest" hidden >>
<<reminder year:2009 month:2 day:14 title:"09:00-- Patricia Visit" hidden >>
<<reminder year:2009 month:2 day:15 title:"09:00-- Patricia Visit" hidden >>
/***
|''Name''|ActivitiesMacro|
|''Description''|Adds a reminder macro to the current tiddler |
|''Author''|Michael Borck|
|''Version''|0.2.5|
|''Date''|4 Dec 2008|
|''Status''|@@beta@@|
|''Source''|http://schedule.tiddlyspot.com/|
|''Copyright''|2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''Feedback''|borck.m@gmail.com|
|''CoreVersion''|2.4|
|''Type''|Macro|
|''Keywords''|timetable, schedule, appointments, hard landscape, macro, reminders|
!Description
This macro adds a reminder to the current tiddler and is an extension/port of the newReminder macro. It provides an alternative tool to construct a reminder. When used in conjunction with the schedule macro the start and end promts are used to schedule the event. If DatePicker is installed it will use that otherwise it will use a custom date picker (the same one provided in newReminder).
!Usage
!Usage
{{{<<addActivity [buttonName]>>>}}}
Where {{{[buttonName]}}} is a name you give to the slider button created.
!!!Code
***/
//{{{
if (!version.extensions.activities) {
version.extensions.activites = {
major: 0,
minor: 2,
revision: 5,
date: new Date(2008, 4, 12),
source: "http://schedule.tiddlyspot.com/"
};
config.macros.addActivity = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
if (DatePicker) // Nice calendar popup
{
var format = "DD MMM YYYY";
var dateBox = 'When:<input type="text" size="15" name="dateBox" value="' + new Date().formatString(format) + '">';
}
else // build our own date picker
{
var today = new Date();
dateBox = 'Year: <select name="year"><option value="">Every year' + '</option>';
for (var i = 0; i < 5; i++) {
dateBox += '<option' + ((i == 0) ? ' selected': '') + ' value="' + (today.getFullYear() + i) + '">' + (today.getFullYear() + i) + '</option>';
}
dateBox += '</select> Month:<select name="month">' + '<option value="">Every month</option>';
for (i = 0; i < 12; i++) {
dateBox += '<option' + ((i == today.getMonth()) ? ' selected': '') + ' value="' + (i + 1) + '">' + config.messages.dates.months[i] + '</option>';
}
dateBox += '</select> Day:<select name="day">' + '<option value="">Every day</option>';
for (i = 1; i < 32; i++) {
dateBox += '<option' + ((i == (today.getDate())) ? ' selected': '') + ' value="' + i + '">' + i + '</option>';
}
}
// Create form elements
var start = 'From:<input type="text" size="5" name="start" value="09:00"' + 'onfocus="this.select();">';
var end = 'to <input type="text" size="5" name="end" value="09:00"' + 'onfocus="this.select();">';
var desc = 'What:<input type="text" size="41" name="title" ' + 'value="Please enter a description" onfocus="this.select();">';
var btn = '<input type="button" value="add" ' + 'onclick="config.macros.addActivity.addEventToTiddler(this.form)">';
var once = '<input type="radio" name="repeat" value="once" checked> Once';
var daily = '<input type="radio" name="repeat" value="daily"> Daily';
var weekly = '<input type="radio" name="repeat" value="weekly"> Weekly';
var twoWeeks = '<input type="radio" name="repeat" value="twoWeeks"> Every 2 weeks';
var fourWeeks = '<input type="radio" name="repeat" value="fourWeeks"> Every 4 weeks';
var monthly = '<input type="radio" name="repeat" value="monthly"> Monthly';
var yearly = '<input type="radio" name="repeat" value="yearly"> Yearly';
var hidden = 'Hide: <input type="checkbox" name="hidden" value="hidden" checked>';
var frequency = '<div>How often:' + once + daily + weekly + twoWeeks + fourWeeks + monthly + yearly + '</div>';
// Construct form
var formstring = '<br><html><form>' + desc + '<br><br>' + dateBox + ' ' + start + ' ' + end + '<br><br>' + frequency + '<br>' + hidden + '<br>' + btn + '</form></html>';
var btnName = params[0] || "Add Activity";
var panel = config.macros.slider.createSlider(place, null, btnName, "Open a form to add a new hidden reminder to this tiddler");
wikify(formstring, panel, null, store.getTiddler(params[1]));
// Form built, now attach calendar popup
if (DatePicker) {
var cb = function(el, objDate) {
el.value = objDate.formatString(format);
};
var box = document.getElementsByName("dateBox")[0];
DatePicker.create(box, new Date(), cb);
}
}
};
config.macros.addActivity.addEventToTiddler = function(form) {
// Determine where to write the macro
var title = window.story.findContainingTiddler(form).id.substr(7);
var tiddler = store.getTiddler(title);
// Determine options for reminder
var eventDate = new Date(form.dateBox.value);
var year = eventDate.getFullYear() || "";
var month = eventDate.getMonth() ? (eventDate.getMonth() + 1) : "";
var day = eventDate.getDate() || "";
var frequency = "once";
for (i = 0; i < form.repeat.length; i++) {
if (form.repeat[i].checked) {
frequency = form.repeat[i].value;
}
}
var recurring = "";
switch (frequency) {
case "once":
break;
case "daily":
recurring = 1;
break;
case "weekly":
recurring = 7;
break;
case "twoWeeks":
recurring = 14;
break;
case "fourWeeks":
recurring = 28;
break;
case "monthly":
month = "";
break
case "yearly":
recurring = 365;
break
}
// Build reminder macro
var txt = '\n<<reminder ';
txt += year ? 'year:' + year + ' ': "";
txt += month ? 'month:' + month + ' ': "";
txt += day ? 'day:' + day + ' ': "";
txt += recurring ? 'recurdays:' + recurring + ' ': "";
txt += form.start.value ? 'title:"' + form.start.value: ""
txt += form.start.value && form.end.value ? '-' + form.end.value: "";
txt += form.title.value ? ' ' + form.title.value + '" ': "";
txt += form.hidden.checked ? ' hidden ': "";
txt += ' >>';
// Write the macro and refresh tiddler
tiddler.set(null, tiddler.text + txt);
window.story.refreshTiddler(title, 1, true);
store.setDirty(true);
};
}
//}}}
This is a list of all appointments for the next 365 days. Use this to view and edit all appointments.
----
{{appta threecolumns{
<<schedule view:agenda hourFrom:8 span:13 shadow:on duration:365>>
}}}
<<forEachTiddler
where 'tiddler.tags.contains("contact")'
sortBy 'tiddler.data("lastname") && tiddler.data("firstname")'
write
'"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("email")+"| [[here|"+tiddler.title+"]]|\n"'
>>
<<forEachTiddler
where 'tiddler.tags.contains("contact")'
sortBy 'tiddler.data("lastname")'
write
'"|"+tiddler.data("firstname")+" "+tiddler.data("lastname")+"|"+tiddler.data("phone")+"| [[here|"+tiddler.title+"]]|\n"'
>>
<<siteMap [[Another New project]] . sliders>>
<<forEachTiddler where 'tiddler.tags.contains("Ask self regularly")' sortBy 'tiddler.title'>>
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span style="padding-right:0em;" macro='tagger'></span><span macro='newThere label:"make subtopic"'></span></div>
<span class='title' macro='view title'></span>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<div class="tagglyTagging" macro="tagglyTagging"></div>
<!--}}}-->
/***
|''Name:''|CalendarPlugin|
|''Source:''|http://www.TiddlyTools.com/#CalendarPlugin|
|''Author:''|SteveRumsby|
|''License:''|unknown|
|''~CoreVersion:''|2.0.10|
[Snip - see plugin documentation at the link above]
!!!!!Configuration:
<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|
!!!!!Syntax:
|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|
|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|
|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|
|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|
|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|
***/
// //Modify this section to change the text displayed for the month and day names, to a different language for example. You can also change the format of the tiddler names linked to from each date, and the colours used.
//{{{
config.macros.calendar = {};
config.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];
config.macros.calendar.weekendbg = "#c0c0c0";
config.macros.calendar.monthbg = "#e0e0e0";
config.macros.calendar.holidaybg = "#ffc0c0";
//}}}
// //''Code section:''
// (you should not need to alter anything below here)//
//{{{
if(config.options.txtCalFirstDay == undefined)
config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
config.options.txtCalStartOfWeekend = 5;
if(config.options.chkDisplayWeekNumbers == undefined)//wn**
config.options.chkDisplayWeekNumbers = false;
if(config.options.chkDisplayWeekNumbers)
config.options.txtCalFirstDay = 0;
config.macros.calendar.tiddlerformat = "0DD/0MM/YYYY"; // This used to be changeable - for now, it isn't// <<smiley :-(>>
version.extensions.calendar = { major: 0, minor: 6, revision: 0, date: new Date(2006, 1, 22)};
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
//}}}
// //Is the given date a holiday?
//{{{
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;
}
//}}}
// //The main entry point - the macro handler.
// //Decide what sort of calendar we are creating (month or year, and which month or year)
// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.
// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//
// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//
// ELS 2006.05.29: add journalDateFmt handling//
//{{{
config.macros.calendar.handler = function(place,macroName,params)
{
var calendar = createTiddlyElement(place, "table", null, "calendar", null);
var tbody = createTiddlyElement(calendar, "tbody", null, null, null);
var today = new Date();
var year = today.getYear();
if (year<1900) year+=1900;
// get format for journal link by reading from SideBarOptions (ELS 5/29/06 - based on suggestion by Martin Budden)
var text = store.getTiddlerText("SideBarOptions");
this.journalDateFmt = "DD-MMM-YYYY";
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]; }
if (params[0] == "thismonth")
{
cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, today.getMonth());
}
else if (params[0] == "lastmonth") {
var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
}
else if (params[0] == "nextmonth") {
var month = today.getMonth()+1; if (month>11) { month=0; year++; }
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
}
else {
if (params[0]) year = params[0];
if(params[1])
{
cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, params[1]-1);
}
else
{
cacheReminders(new Date(year, 0, 1, 0, 0), 366);
createCalendarYear(tbody, year);
}
}
window.reminderCacheForCalendar = null;
}
//}}}
//{{{
//This global variable is used to store reminders that have been cached
//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", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarYear(calendar, year)
{
var row;
row = createTiddlyElement(calendar, "tr", null, null, null);
var back = createTiddlyElement(row, "td", null, null, null);
var backHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, year-1);
};
createTiddlyButton(back, "<", "Previous year", backHandler);
back.align = "center";
var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
yearHeader.align = "center";
//yearHeader.setAttribute("colSpan", 19);
yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**
var fwd = createTiddlyElement(row, "td", null, null, null);
var fwdHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, year+1);
};
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", null, null, null);
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", null, null, null);
createCalendarDayHeader(row, 3);
createCalendarDayRows(cal, year, mon);
}
//}}}
//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
var month;
if(nav) {
var back = createTiddlyElement(row, "td", null, null, null);
back.align = "center";
back.style.background = config.macros.calendar.monthbg;
/*
back.setAttribute("colSpan", 2);
var backYearHandler = function() {
var newyear = year-1;
removeChildren(cal);
cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, mon);
};
createTiddlyButton(back, "<<", "Previous year", backYearHandler);
*/
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);
};
createTiddlyButton(back, "<", "Previous month", backMonHandler);
month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
// month.setAttribute("colSpan", 3);
// month.setAttribute("colSpan", 5);
month.setAttribute("colSpan", config.options.chkDisplayWeekNumbers?6:5);//wn**
var fwd = createTiddlyElement(row, "td", null, null, null);
fwd.align = "center";
fwd.style.background = config.macros.calendar.monthbg;
// fwd.setAttribute("colSpan", 2);
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);
};
createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
/*
var fwdYear = createTiddlyElement(row, "td", null, null, null);
var fwdYearHandler = function() {
var newyear = year+1;
removeChildren(cal);
cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, mon);
};
createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);
*/
} else {
month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
//month.setAttribute("colSpan", 7);
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);
createTiddlyElement(row, "td", null, null, "w"+ww.getWeek());//wn**
}
else createTiddlyElement(row, "td", null, null, null);//wn**
}
for(i = 0; i < col; i++) {
createTiddlyElement(row, "td", null, null, null);
}
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", null, null, null);
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 2005.10.30: use <<date>> macro's showDate() function to create popup
if (window.showDate) {
showDate(daycell,celldate,"popup","DD",config.macros.calendar.journalDateFmt,true, isaWeekend); // ELS 5/29/06 - use journalDateFmt
} else {
if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
var title = celldate.formatString(config.macros.calendar.tiddlerformat);
if(calendarIsHoliday(celldate)) {
daycell.style.background = config.macros.calendar.holidaybg;
}
if(window.findTiddlersWithReminders == null) {
var link = createTiddlyLink(daycell, title, false);
link.appendChild(document.createTextNode(day));
} else {
var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
}
}
}
day++;
}
}
//}}}
// //We've clicked on a day in a calendar - create a suitable pop-up of options.
// //The pop-up should contain:
// // * a link to create a new entry for that date
// // * a link to create a new reminder for that date
// // * an <hr>
// // * the list of reminders for that date
//{{{
function onClickCalendarDate(e)
{
var button = this;
var date = button.getAttribute("title");
var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));
date = dat.formatString(config.macros.calendar.tiddlerformat);
var popup = createTiddlerPopup(this);
popup.appendChild(document.createTextNode(date));
var newReminder = function() {
var t = store.getTiddlers(date);
displayTiddler(null, date, 2, null, null, false, false);
if(t) {
document.getElementById("editorBody" + date).value += "\n<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) +
" year:" + (dat.getYear()+1900) + " title: >>";
} else {
document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) +
" year:" + (dat.getYear()+1900) + " title: >>";
}
};
var link = createTiddlyButton(popup, "New reminder", null, newReminder);
popup.appendChild(document.createElement("hr"));
var t = findTiddlersWithReminders(dat, [0,14], null, 1);
for(var i = 0; i < t.length; i++) {
link = createTiddlyLink(popup, t[i].tiddler, false);
link.appendChild(document.createTextNode(t[i].tiddler));
}
}
//}}}
//{{{
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", null, null, null);
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", null, null, null);
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", null, null, null);
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", null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
}
}
//}}}
// //ELS 2005.10.30: added styles
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:5px !important; }", "calendarStyles");
//}}}
// // override cookie settings for CalendarPlugin:
//{{{
config.options.txtCalFirstDay=6;
config.options.txtCalStartOfWeekend=5;
//}}}
<<siteMap [[ChangeNotes]] . sliders>>
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|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;
}
}
//}}}
<<forEachTiddler where 'tiddler.tags.contains("Clean, repair")' sortBy 'tiddler.title'>>
/***
|Name:|CloseOnCancelPlugin|
|Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.commands.cancelTiddler,{
handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler,
handler: function(event,src,title) {
this.handler_mptw_orig_closeUnsaved(event,src,title);
if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))
story.closeTiddler(title,true);
return false;
}
});
//}}}
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #110077
PrimaryMid: #110077
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Use ~TiddlyDu3 to create a modest database of your friends and business contacts.
Click on 'New contact group' in the Contacts tab to create a new category of contacts (e.g., 'Friends', 'Family members', 'Fast food take-out', etc). Click 'done' to go to view mode.
Within the contact group tiddler, click on *Add contact* in the toolbar. A new contact tiddler will appear. Give the contact tiddler a title, paste the title between the brackets in the slider menu. Then go to view mode to fill in the forms with your contact's data.
The Contacts index on the right will automatically add your contact when you refresh. The Contacts group index will add the groups and will also create an automatically generated, expandable list of contacts within each group. Click on the black arrow to see the contacts within each group.
You can also work from the bottom up, clicking 'Contact' above, giving the tiddler a title, then in view mode select the contact group to which this contact properly belongs.
<<siteMap [[Enter the name for your new contact group here, too]] . sliders>>
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span class='newbutton' style='padding-right: 0.5em;' macro='newHere title:"Name your new contact and click done to add data" label:"*New contact for this contact group*" text:{{"<<formTiddler NewContactTemplate\>\>"}} tag:"contact"'></span></div>
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<<forEachTiddler where 'tiddler.tags.contains("Correspondence")' sortBy 'tiddler.title'>>
<<newTiddler label:"New Master Topic" title:'MyNewMasterTopic' text:{{store.getTiddlerText('NewMasterTopic')}} tag:''>>
#''To create a'' new master topic click ''New Master Topic'' button below.
<<tiddler CreateNewMasterTopic>>
## ''Change the name of the tiddler'' ~MyNewMasterTopic to __YourTopic name__.
## ''In the body of the tiddler replace'' MYNEWMASTERTOPIC (3 places) with __YourTopic name__ as above.
2: ''Add your new topic'' to the MainMenu My Notes tabs like this:
{{{<<tabs "" "TiddlyDu3" "TiddlyDu3" "TiddlyDu3" "YourTopic" "YourTopic" "YourTopic">>}}}
----
#''To create subTopics:'' Click ''subTopic'' next to the Master Topic i.e. @@color:#008;subTopic | refresh@@ and follow the instructions provided.
##''Then to create sub-subTopics:'' open the relevant subTopic and __''in its toolbar''__ click @@color:#008;'make subtopic'@@. (Note: This simply makes new tiddler tagged with title of the original tiddler and a script makes it a subTopic of that tiddler)
##''Just hit the 'refresh topic index' button'' to see the new additions to the menu. Click on the arrows (►) to open the levels of the index.
This list is automatically generated when you add 'urgent', 'possbility' or 'waiting' as a status for your tasks. Use this as your to-do list headquarters.
|!Urgent|!Possibly this week|
|vertical-align: top;padding-right: 20px;<<forEachTiddler where 'tiddler.tags.contains("Urgent")' write '"[[" + tiddler.title+"]]\n"'>>|vertical-align: top;padding-right: 20px;<<forEachTiddler where 'tiddler.tags.contains("Possibly")' write '"[[" + tiddler.title+"]]\n"'>>|
|!Waiting|!Ongoing|
|vertical-align: top;padding-right: 20px;<<forEachTiddler where 'tiddler.tags.contains("Waiting")' write '"[[" + tiddler.title+"]]\n"'>>|vertical-align: top;padding-right: 20px;<<forEachTiddler where 'tiddler.tags.contains("Ongoing")' write '"[[" + tiddler.title+"]]\n"'>>|
<<forEachTiddler where 'tiddler.tags.contains("Data entry")' sortBy 'tiddler.title'>>
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).
Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers.
''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.
''Access and Modify Tiddler Data''
You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields.
These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//
''Data Representation in a Tiddler''
The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]].
//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}
The data section is not displayed when viewing the tiddler (see also "The showData Macro").
Beside the data section a tiddler may have all kind of other content.
Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.
''Saving Changes''
The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.
''Notifications''
No notifications are sent when a tiddler's data value is changed through the "setData" methods.
''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.
''The showData Macro''
By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:
''Syntax:''
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
!Revision history
* v1.0.6 (2006-08-26)
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed:
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features:
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed:
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// DataTiddlerPlugin
//============================================================================
//============================================================================
// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {
version.extensions.DataTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006, 7, 26),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) {
TiddlyWiki.prototype.getTiddler = function(title) {
var t = this.tiddlers[title];
return (t !== undefined && t instanceof Tiddler) ? t : null;
};
}
//============================================================================
// DataTiddler Class
//============================================================================
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
function DataTiddler() {
}
DataTiddler = {
// Function to stringify a JavaScript value, producing the text for the data section content.
// (Must match the implementation of DataTiddler.parse.)
//
stringify : null,
// Function to parse the text for the data section content, producing a JavaScript value.
// (Must match the implementation of DataTiddler.stringify.)
//
parse : null
};
// Ensure access for IE
window.DataTiddler = DataTiddler;
// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------
// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};
// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler+ "("+t+")";
}
DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};
// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...)
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataObject(t);
};
// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.readDataSectionText(t);
};
// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------
// Internal.
//
// The original JSONError is not very user friendly,
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
if (ex.name == 'JSONError') {
ex.toString = function() {
return ex.name + ": "+ex.message+" ("+ex.text+")";
};
}
return ex;
};
// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
if (t.dataObject === undefined) {
var data = DataTiddler.readData(t);
t.dataObject = (data) ? data : {};
}
return t.dataObject;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
return (value === undefined) ? defaultValue : value;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
var oldValue = data[field];
if (value == defaultValue) {
if (oldValue !== undefined) {
delete data[field];
DataTiddler.save(tiddler);
}
return;
}
data[field] = value;
DataTiddler.save(tiddler);
};
// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
if (matches === null || !matches[2]) {
return null;
}
return matches[2];
};
// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
var text = DataTiddler.readDataSectionText(tiddler);
try {
return text ? DataTiddler.parse(text) : null;
} catch(ex) {
throw DataTiddler.extendJSONError(ex);
}
};
// Internal.
//
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
return DataTiddler.stringify(data);
};
// Internal.
//
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
var index = s.indexOf(subString, startIndex);
while ((index > 0) && (s[index-1] == '~')) {
index = s.indexOf(subString, index+1);
}
return index;
};
// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
// Special care must be taken to handle "<data>" and "</data>" texts inside
// a data section.
// Also take care not to use an escaped <data> (i.e. "~<data>") as the start
// of a data section. (Same for </data>)
// NOTE: we are explicitly searching for a data section that contains a JSON
// string, i.e. framed with braces. This way we are little bit more robust in
// case the tiddler contains unescaped texts "<data>" or "</data>". This must
// be changed when using a different stringifier.
var startTagText = "<data>{";
var endTagText = "}</data>";
var startPos = 0;
// Find the first not escaped "<data>".
var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
if (startDataTagIndex < 0) {
return null;
}
// Find the *last* not escaped "</data>".
var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
if (endDataTagIndex < 0) {
return null;
}
var nextEndDataTagIndex;
while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
endDataTagIndex = nextEndDataTagIndex;
}
return {
prefixEnd: startDataTagIndex,
dataStart: startDataTagIndex+(startTagText.length)-1,
dataEnd: endDataTagIndex,
suffixStart: endDataTagIndex+(endTagText.length)
};
};
// Internal.
//
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
var text = tiddler.text;
var info = DataTiddler.getDataSectionInfo(text);
if (!info) {
return null;
}
var prefix = text.substr(0,info.prefixEnd);
var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
var suffix = text.substr(info.suffixStart);
return [text, prefix, data, suffix];
};
// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change).
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected.
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send.
//
// This method should only be called when the data really has changed.
//
// @param tiddler
// the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
var prefix;
var suffix;
if (matches === null) {
prefix = tiddler.text;
suffix = "";
} else {
prefix = matches[1];
suffix = matches[3];
}
var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
var newText =
(dataText !== null)
? prefix + "<data>" + dataText + "</data>" + suffix
: prefix + suffix;
if (newText != tiddler.text) {
// make the change in the tiddlers text
// ... see DataTiddler.MyTiddlerChangedFunction
tiddler.isDataTiddlerChange = true;
// ... do the action change
tiddler.set(
tiddler.title,
newText,
config.options.txtUserName,
config.options.chkForceMinorUpdate? undefined : new Date(),
tiddler.tags);
// ... see DataTiddler.MyTiddlerChangedFunction
delete tiddler.isDataTiddlerChange;
// Mark the store as dirty.
store.dirty = true;
// AutoSave if option is selected
if(config.options.chkAutoSave) {
saveChanges();
}
}
};
// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
// Remove the data object from the tiddler when the tiddler is changed
// by code other than DataTiddler code.
//
// This is necessary since the data object is just a "cached version"
// of the data defined in the data section of the tiddler and the
// "external" change may have changed the content of the data section.
// Thus we are not sure if the data object reflects the data section
// contents.
//
// By deleting the data object we ensure that the data object is
// reconstructed the next time it is needed, with the data defined by
// the data section in the tiddler's text.
// To indicate that a change is a "DataTiddler change" a temporary
// property "isDataTiddlerChange" is added to the tiddler.
if (this.dataObject && !this.isDataTiddlerChange) {
delete this.dataObject;
}
// call the original code.
DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};
//============================================================================
// Formatters
//============================================================================
// This formatter ensures that "~<data>" is rendered as "<data>". This is used to
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
name: "data-escape",
match: "~<\\/?data>",
handler: function(w) {
w.outputText(w.output,w.matchStart + 1,w.nextMatch);
}
} );
// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
name: "data",
match: "<data>",
handler: function(w) {
var info = DataTiddler.getDataSectionInfo(w.source);
if (info && info.prefixEnd == w.matchStart) {
w.nextMatch = info.suffixStart;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
} );
//============================================================================
// Tiddler Class Extension
//============================================================================
// "Hijack" the changed method ---------------------------------------------------
DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;
// Define accessor methods -------------------------------------------------------
// Returns the value of the given data field of the tiddler. When no such field
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
return (field)
? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
: DataTiddler.getTiddlerDataObject(this);
};
// Sets the value of the given data field of the tiddler to the value. When the
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};
//============================================================================
// showData Macro
//============================================================================
config.macros.showData = {
// Standard Properties
label: "showData",
prompt: "Display the values stored in the data section of the tiddler"
};
config.macros.showData.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the optional "JSON"
var showInJSONFormat = false;
if ((i < params.length) && params[i] == "JSON") {
i++;
showInJSONFormat = true;
}
var tiddlerName = story.findContainingTiddler(place).id.substr(7);
if (i < params.length) {
tiddlerName = params[i];
i++;
}
// --- Processing ------------------------------------------
try {
if (showInJSONFormat) {
this.renderDataInJSONFormat(place, tiddlerName);
} else {
this.renderDataAsTable(place, tiddlerName);
}
} catch (e) {
this.createErrorElement(place, e);
}
};
config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
var text = DataTiddler.getDataText(tiddlerName);
if (text) {
createTiddlyElement(place,"pre",null,null,text);
}
};
config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
var text = "|!Name|!Value|\n";
var data = DataTiddler.getDataObject(tiddlerName);
if (data) {
for (var i in data) {
var value = data[i];
text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
}
}
wikify(text, place);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.showData.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".showDataError{color: #ffffff;background-color: #880000;}",
"showData");
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... TiddlyWiki Core
/*global createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global DataTiddler */
// ... JSON
/*global JSON */
/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
throw a 'JSONError' exception if there is an error.
*/
var JSON = {
copyright: '(c)2005 JSON.org',
license: 'http://www.crockford.com/JSON/license.html',
/*
Stringify a JavaScript value, producing a JSON text.
*/
stringify: function (v) {
var a = [];
/*
Emit a string.
*/
function e(s) {
a[a.length] = s;
}
/*
Convert a value.
*/
function g(x) {
var c, i, l, v;
switch (typeof x) {
case 'object':
if (x) {
if (x instanceof Array) {
e('[');
l = a.length;
for (i = 0; i < x.length; i += 1) {
v = x[i];
if (typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(v);
}
}
e(']');
return;
} else if (typeof x.toString != 'undefined') {
e('{');
l = a.length;
for (i in x) {
v = x[i];
if (x.hasOwnProperty(i) &&
typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(i);
e(':');
g(v);
}
}
return e('}');
}
}
e('null');
return;
case 'number':
e(isFinite(x) ? +x : 'null');
return;
case 'string':
l = x.length;
e('"');
for (i = 0; i < l; i += 1) {
c = x.charAt(i);
if (c >= ' ') {
if (c == '\\' || c == '"') {
e('\\');
}
e(c);
} else {
switch (c) {
case '\b':
e('\\b');
break;
case '\f':
e('\\f');
break;
case '\n':
e('\\n');
break;
case '\r':
e('\\r');
break;
case '\t':
e('\\t');
break;
default:
c = c.charCodeAt();
e('\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16));
}
}
}
e('"');
return;
case 'boolean':
e(String(x));
return;
default:
e('null');
return;
}
}
g(v);
return a.join('');
},
/*
Parse a JSON text, producing a JavaScript value.
*/
parse: function (text) {
var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
token,
operator;
function error(m, t) {
throw {
name: 'JSONError',
message: m,
text: t || operator || token
};
}
function next(b) {
if (b && b != operator) {
error("Expected '" + b + "'");
}
if (text) {
var t = p.exec(text);
if (t) {
if (t[2]) {
token = null;
operator = t[2];
} else {
operator = null;
try {
token = eval(t[1]);
} catch (e) {
error("Bad token", t[1]);
}
}
text = text.substring(t[0].length);
} else {
error("Unrecognized token", text);
}
} else {
token = operator = undefined;
}
}
function val() {
var k, o;
switch (operator) {
case '{':
next('{');
o = {};
if (operator != '}') {
for (;;) {
if (operator || typeof token != 'string') {
error("Missing key");
}
k = token;
next();
next(':');
o[k] = val();
if (operator != ',') {
break;
}
next(',');
}
}
next('}');
return o;
case '[':
next('[');
o = [];
if (operator != ']') {
for (;;) {
o.push(val());
if (operator != ',') {
break;
}
next(',');
}
}
next(']');
return o;
default:
if (operator !== null) {
error("Missing value");
}
k = token;
next();
return k;
}
}
next();
return val();
}
};
/***
!Setup the data serialization
***/
DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;
//}}}
/***
|''Name:''|DatePickerLibrary|
|''Description:''|DatePicker library for use with macros|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Code Repository:''|http://svn.tiddlywiki.org/Trunk/contributors/SaqImtiaz/libraries/DatePicker.js|
|''Version:''|0.9|
|''Date:''|06/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.3.0|
***/
// /%
//!BEGIN-PLUGIN-CODE
//{{{
function $id(n) {
return document.getElementById(n);
}
DatePicker = {
days : ['S','M','T','W','T','F','S'],
cells : new Array(42),
setup : function(){
var cte = createTiddlyElement;
var table = this.table = cte(null,"table","datePickerTable");
table.style.display = 'none';
document.body.appendChild(table);
var thead = cte(table,"thead");
var hRow = cte(thead,"tr");
hRow.onclick = stopEvent;
cte(hRow,"td",null,"datePickerNav","<<").onclick = DatePicker.prevm;
cte(hRow,"td","datePickerMNS",null,null,{colSpan:"5"});
cte(hRow,"td",null,"datePickerNav",">>",{align:"right"}).onclick=DatePicker.nextm;
var tbody = cte(table,"tbody","datePickerTableBody");
var dayRow = cte(tbody,"tr",null,"datePickerDaysHeader");
for (var i=0; i<this.days.length; i++){
cte(dayRow,"td",null,null,this.days[i]);
}
},
show : function(el,dateObj,cb) {
var me = DatePicker;
var now = me.now = new Date();
if (!dateObj)
dateObj = now;
me.root = el;
if (cb)
me.root.datePickerCallback = cb;
me.scc = { m : now.getMonth(), y : now.getFullYear(), d : now.getDate() };
Popup.place(el,me.table,{x:0,y:1});
var cur = [dateObj.getDate(),dateObj.getMonth()+1,dateObj.getFullYear()];
me.cc = { m : cur[1]-1, y : cur[2] };
me.sd = { m : cur[1]-1, y : cur[2], d : cur[0] };
me.fillCalendar(cur[0],me.scc.d,cur[1]-1,cur[2]);
},
fillCalendar : function(hd,today,cm,cy) {
var me = DatePicker;
var sd = me.now.getDate();
var td = new Date(cy,cm,1)
var cd = td.getDay();
$id('datePickerMNS').innerHTML = td.formatString('MMM YYYY')
var tbody = $id('datePickerTableBody');
removeChildren(tbody);
var dowRow = createTiddlyElement(tbody,"tr",null,"datePickerDowRow");
for (var d=0;d<=7;d++) {
// dow headings
createTiddlyElement(dowRow,"td",null,null,DatePicker.days[d]);
}
var days = (new Date(cy, cm+1, 0)).getDate();
var day = 1;
for (var j=1;j<=6;j++) { //rows
var row = createTiddlyElement(tbody,"tr",null,"datePickerDayRow");
for (var t=1; t<=7; t++) { //cells
var d = 7 * (j-1) - (-t); //id key
if ( (d >= (cd -(-1))) && (d<=cd-(-(days))) ) {
var dip = ( ((d-cd < sd) && (cm == me.scc.m) && (cy == me.scc.y)) || (cm < me.scc.m && cy == me.scc.y) || (cy < me.scc.y) );
var htd = ( (hd != '') && (d-cd == hd) );
var hToday = ( (today != '') && (d-cd == today) && cy == me.scc.y && cm == me.scc.m );
if (htd)
_class = 'highlightedDate';
else if (dip)
_class = 'oldDate';
else if (hToday && ! htd)
_class = 'todayDate';
else
_class = 'defaultDate';
if (t == 1 || t == 7) {
// weekend
_class += ' weekend';
}
var cell = createTiddlyElement(row,"td","datePickerDay"+d,_class,d-cd);
cell.onmouseover = function(e){addClass(this,'tdover');};
cell.onmouseout = function(e){removeClass(this,'tdover');};
cell.onclick = me.selectDate;
me.cells[d] = new Date(cy,cm,d-cd);
}
else {
var cell = createTiddlyElement(row,"td","datePickerDay"+d,"emptyDate");
}
day++;
}
if(day > days + cd)
break;
}
},
nextm : function() {
var me = DatePicker;
me.cc.m += 1;
if (me.cc.m >= 12) {
me.cc.m = 0;
me.cc.y++;
}
me.fillCalendar(me.getDayStatus(me.cc.m,me.cc.y),me.scc.d,me.cc.m,me.cc.y);
return false;
},
prevm : function() {
var me = DatePicker;
me.cc.m -= 1;
if (me.cc.m < 0) {
me.cc.m = 11;
me.cc.y--;
}
me.fillCalendar(me.getDayStatus(me.cc.m,me.cc.y),me.scc.d,me.cc.m,me.cc.y);
return false;
},
getDayStatus : function(ccm,ccy){
return (ccy == this.sd.y && ccm == this.sd.m)? this.sd.d : '';
},
selectDate : function(ev){
var e = ev ? ev : window.event;
var me = DatePicker;
var date = me.cells[resolveTarget(e).id.substring(13,resolveTarget(e).id.length)];
if (me.root.datePickerCallback && typeof me.root.datePickerCallback == 'function')
me.root.datePickerCallback(me.root,date);
$id('datePickerTable').style.display = 'none';
return false;
},
onclick : function(ev){
$id("datePickerTable").style.display = 'none';
return false;
},
create : function(el,dateObj,cb){
el.onclick = el.onfocus = function(e){DatePicker.show(el,dateObj,cb);stopEvent(e)};
},
css: "table#datePickerTable td.datePickerNav {\n"+
" cursor:pointer;\n"+
"}\n"+
"\n"+
".datePickerDaysHeader td {\n"+
" text-align:center;\n"+
" background:#ABABAB;\n"+
" font:12px Arial;\n"+
"}\n"+
"\n"+
".datePickerDayRow td {\n"+
" width:18px;\n"+
" height:18px;\n"+
"}\n"+
"\n"+
"td#datePickerMNS, td.datePickerNav {\n"+
" font:bold 13px Arial;\n"+
"}\n"+
"\n"+
"table#datePickerTable {\n"+
" position:absolute;\n"+
" border-collapse:collapse;\n"+
" background:#FFFFFF;\n"+
" border:1px solid #ABABAB;\n"+
" display:none; \n"+
"}\n"+
"\n"+
"table#datePickerTable td{\n"+
" padding: 3px;\n"+
"}\n"+
"\n"+
"td#datePickerMNS {\n"+
" text-align: center;\n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td {\n"+
" background-color : #C4D3EA;\n"+
" cursor : pointer;\n"+
" border : 1px solid #6487AE;\n"+
" text-align : center;\n"+
" font : 10px Arial;\n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td.defaultDate {\n"+
" color : #333333; \n"+
" text-decoration : none; \n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td.emptyDate {\n"+
" cursor:default; \n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td.oldDate {\n"+
" color : #ABABAB;\n"+
" text-decoration : line-through;\n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td.highlightedDate {\n"+
" background : #FFF799;\n"+
" font-weight : bold;\n"+
" color : #333333;\n"+
"}\n"+
"\n"+
"tr.datePickerDayRow td.todayDate {\n"+
" font-weight : bold;\n"+
" color : red;\n"+
"}\n"+
"\n"+
"table#datePickerTable tr.datePickerDayRow td.tdover {\n"+
" background:#fc6;\n"+
"}",
init : function(){
this.setup();
addEvent(document,'click',DatePicker.onclick);
config.shadowTiddlers['StyleSheetDatePicker'] = this.css;
if(store)
store.addNotification('StyleSheetDatePicker',refreshStyles);
}
};
DatePicker.init();
//}}}
//!END-PLUGIN-CODE
// %/
/***
|Name|DatePlugin|
|Source|http://www.TiddlyTools.com/#DatePlugin|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|formatted dates plus popup menu with 'journal' link, changes and (optional) reminders|
There are quite a few calendar generators, reminders, to-do lists, 'dated tiddlers' journals, blog-makers and GTD-like schedule managers that have been built around TW. While they all have different purposes, and vary in format, interaction, and style, in one way or another each of these plugins displays and/or uses date-based information to make finding, accessing and managing relevant tiddlers easier. This plugin provides a general approach to embedding dates and date-based links/menus within tiddler content.
!!!!!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
<<<
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.
|please see [[DatePluginInfo]] for additional revision details|
2005.10.30 [0.9.0] pre-release
<<<
!!!!!Code
***/
//{{{
version.extensions.DatePlugin= {major: 2, minor: 7, revision: 0, date: new Date(2008,3,8)};
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"
holidays: [ "01/01", "07/04", "07/24", "11/24" ], // NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)
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 ]
};
config.macros.date.handler = function(place,macroName,params)
{
// do we want to see a link, a popup, or just a formatted date?
var mode="display";
if (params[0]=="display") { mode=params[0]; params.shift(); }
if (params[0]=="popup") { mode=params[0]; params.shift(); }
if (params[0]=="link") { mode=params[0]; params.shift(); }
// get the date
var now = new Date();
var date = now;
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)
{
if (!mode) mode="display";
if (!format) format=config.macros.date.format;
if (!linkformat) linkformat=config.macros.date.linkformat;
if (!autostyle) autostyle=false;
// 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)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
var popup = Popup.create(this);
if(popup) {
// always show dated tiddler link (or just date, if readOnly) at the top...
if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))
createTiddlyLink(popup,this.date.formatString(this.linkformat),true);
else
createTiddlyText(popup,this.date.formatString(this.linkformat));
if (!config.options.chkDatePopupHideCreated)
addCreatedsToPopup(popup,this.date,this.format);
if (!config.options.chkDatePopupHideChanged)
addModifiedsToPopup(popup,this.date,this.format);
if (!config.options.chkDatePopupHideTagged)
addTaggedToPopup(popup,this.date,this.linkformat);
if (!config.options.chkDatePopupHideReminders)
addRemindersToPopup(popup,this.date,this.linkformat);
}
Popup.show(popup,false);
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(popup,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(popup,"div",null,null,"created ("+createds.length+")");
for(var t=0; t<createds.length; t++) {
var link=createTiddlyLink(popup,createds[t],false);
link.appendChild(document.createTextNode(indent+createds[t]));
createTiddlyElement(popup,"br",null,null,null);
}
}
}
//}}}
//{{{
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(popup,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(popup,"div",null,null,"changed ("+mods.length+")");
for(var t=0; t<mods.length; t++) {
var link=createTiddlyLink(popup,mods[t],false);
link.appendChild(document.createTextNode(indent+mods[t]));
createTiddlyElement(popup,"br",null,null,null);
}
}
}
//}}}
//{{{
function hasTagged(date,format) // returns true if date is tagging other tiddlers
{
return store.getTaggedTiddlers(date.formatString(format)).length>0;
}
function addTaggedToPopup(popup,when,format)
{
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var tagged=store.getTaggedTiddlers(when.formatString(format));
if (tagged.length) var e=createTiddlyElement(popup,"div",null,null,"tagged ("+tagged.length+")");
for(var t=0; t<tagged.length; t++) {
var link=createTiddlyLink(popup,tagged[t].title,false);
link.appendChild(document.createTextNode(indent+tagged[t].title));
createTiddlyElement(popup,"br",null,null,null);
}
}
//}}}
//{{{
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
// DEBUG var starttime=new Date();
var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);
for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;
// DEBUG var out="Found "+t.length+" reminders in "+((new Date())-starttime+1)+"ms\n";
// DEBUG out+="startdate: "+date.toLocaleDateString()+"\n"+"leadtime: "+leadtime+" days\n\n";
// DEBUG for(var i=0; i<t.length; i++) { out+=t[i].matchedDate.toLocaleDateString()+" "+t[i].params.title+"\n"; }
// DEBUG alert(out);
}
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(popup,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(popup,"div",null,null,"reminders ("+(reminders.length||"none")+")");
for(var t=0; t<reminders.length; t++) {
link = createTiddlyLink(popup,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));
createTiddlyElement(popup,"br",null,null,null);
}
if (readOnly) return; // omit "new reminder..." link
var link = createTiddlyLink(popup,indent+"new reminder...",true); createTiddlyElement(popup,"br");
var title = when.formatString(format);
link.title="add a reminder to '"+title+"'";
link.onclick = function() {
// show tiddler editor
story.displayTiddler(null, title, 2, null, null, false, false);
// find body 'textarea'
var c =document.getElementById("tiddler" + title).getElementsByTagName("*");
for (var i=0; i<c.length; i++) if ((c[i].tagName.toLowerCase()=="textarea") && (c[i].getAttribute("edit")=="text")) break;
// append reminder macro to tiddler content
if (i<c.length) {
if (store.tiddlerExists(title)) c[i].value+="\n"; else c[i].value="";
c[i].value += "<<reminder";
c[i].value += " day:"+when.getDate();
c[i].value += " month:"+(when.getMonth()+1);
c[i].value += " year:"+when.getFullYear();
c[i].value += ' title:"Enter a title" >>';
}
};
}
//}}}
/***
|Name|DatePluginConfig|
|Source|http://www.TiddlyTools.com/#DatePluginConfig|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.6.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|formats, background colors and other optional settings for DatePlugin|
***/
// // Default popup content display options (can be overridden by cookies)
//{{{
if (config.options.chkDatePopupHideCreated===undefined)
config.options.chkDatePopupHideCreated=false;
if (config.options.chkDatePopupHideChanged===undefined)
config.options.chkDatePopupHideChanged=false;
if (config.options.chkDatePopupHideTagged===undefined)
config.options.chkDatePopupHideTagged=false;
if (config.options.chkDatePopupHideReminders===undefined)
config.options.chkDatePopupHideReminders=false;
//}}}
// // show Julian date number below regular date
//{{{
if (config.options.chkShowJulianDate===undefined)
config.options.chkShowJulianDate=false;
//}}}
// // fixed-date annual holidays
//{{{
config.macros.date.holidays=[
"01/01", // NewYearsDay,
"07/04", // US Independence Day
"07/24" // Eric's Birthday (hooray!)
];
//}}}
// // weekend map (1=weekend, 0=weekday)
//{{{
config.macros.date.weekend=[ 1,0,0,0,0,0,1 ]; // day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6
//}}}
// // date display/link formats
//{{{
config.macros.date.format="YYYY.0MM.0DD"; // default date display format
config.macros.date.linkformat="YYYY.0MM.0DD"; // 'dated tiddler' link format
//}}}
// // When displaying a calendar (see [[CalendarPlugin]]), you can customize the colors/styles that are applied to the calendar dates by modifying the values and/or functions below:
//{{{
// default calendar colors
config.macros.date.weekendbg="#c0c0c0";
config.macros.date.holidaybg="#ffaace";
config.macros.date.createdbg="#bbeeff";
config.macros.date.modifiedsbg="#bbeeff";
config.macros.date.linkedbg="#babb1e";
config.macros.date.remindersbg="#c0ffee";
// apply calendar styles
function setDateStyle(place,link,weekend) {
// alias variable names for code readability
var date=link.date;
var fmt=link.linkformat;
var linkto=date.formatString(fmt);
var cmd=config.macros.date;
if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
{ place.style.background = cmd.weekendbg; }
if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
if (hasReminders(date))
{ link.style.textDecoration="underline"; }
if (isToday(date))
{ link.style.border="1px solid black"; }
if (isHoliday(date)&&(cmd.holidaybg!=""))
{ place.style.background = cmd.holidaybg; }
if (hasCreateds(date)&&(cmd.createdbg!=""))
{ place.style.background = cmd.createdbg; }
if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
{ place.style.background = cmd.modifiedsbg; }
if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
{ place.style.background = cmd.linkedbg; }
if (hasReminders(date)&&(cmd.remindersbg!=""))
{ place.style.background = cmd.remindersbg; }
if (isToday(date)&&(cmd.todaybg!=""))
{ place.style.background = cmd.todaybg; }
if (config.options.chkShowJulianDate) {
var m=[0,31,59,90,120,151,181,212,243,273,304,334];
var d=date.getDate()+m[date.getMonth()];
var y=date.getFullYear();
if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0) d++; // after February in a leap year
wikify("@@font-size:80%;<br>"+d+"@@",place);
}
}
//}}}
Hello all,
Something in GoalViewTemplate that was working at first, got messed up
yesterday when I pasted a faulty parameter in the newhere macro. I
changed it to doublequotes from singlequotes in the macro, and it
should be okay now. @Morris, thanks for calling my attention to that!
So for those of you following along, the tiddlers I have fixed are
1. GoalViewTemplate (fixed the title parameter of the newhere macro)
2. EditTemplate (removed unneeded stuff like NoteNote left over from
the No-Brainer Notes EditTemplate) (also reinserted the tag chooser
for Morris, though I personally find it annoying and have never used
it)
3. NewHereMacrowithGiffmexTweak is now NewHerePlugin, and is back to
its original form without the unneeded tweak that was also a carry-
over from NBN.
Import these, or at the very least the first one, from
http://www.giffmex.org/tiddlydu3.html, and you will be in good shape.
@Morris, the welcome tiddler is just a welcome, not a homepage. It's
not something people will need after the initial introductory phase.
If anything, I'm hoping people will use 'Current' as their default
page, not Welcome. And as the welcome tiddler itself says, all the
instructions are found in the help tab (inside the extras tab). That
includes the Welcome tiddler. I don't plan to change that.
Blessings,
Dave
@Morris
1. Thanks for the heads up about the acknowledgements.
2. The idea is that your projects are to help you achieve your goals
and your tasks to help you achieve your projects and goals. So you
should not run into situations where you will delete a life goal and
still have projects and tiddlers tagged with that goal. The smaller
will always get done before the larger. And if you decide you want to
eliminate an unfinished goal from your life, you will most likely also
eliminate the tasks and projects meant to reach that goal. You might
decide to rename your goal, in which case you can use the RenameTag
bookmarklet. In any case, the small number of life goals one ought to
have means that a few orphan tags laying around won't be much of a
problem in terms of file size etc. I think you made a mistake by
removing the new project here button from the GoalViewTemplate. You
are defeating the whole philosophy and purpose of the goal and project
sliders.
3. Good idea to put Help as a first level tab. But you have IFrames
and GTD in that tab, and so they will be forgotten by the user since
they are not 'help' items but features. You could put them in Info,
but that means digging through an extra layer of tabs to add info,
something I use quite frequently and probably others will too. I don't
see an easy but satisfactory solution, since there is only so much
horizontal real estate in the mainmenu. I think that 'Extras' is
general enough to signal to people that it contains things like Help.
And those who take the time to explore the whopping 5 tabs and use the
file for a bit will know it by instinct. So I think I'm going to leave
that one as is.
@Mario
I haven't a clue how to make a TW that works in an iphone. If anyone
wants to take it on, be my guest. Just give me a nod in the
acknowledgements tiddler. I'd love to see the finished product.
Dave
[[This week's appointments]]
<<formTiddler NewContactTemplate>><data>{"firstname":"Dennis","lastname":"Stokes"}</data>
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};
//--
//-- Deprecated code
//--
// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};
// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = 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 text = lookaheadMatch[1];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
createTiddlyElement(w.output,"pre",null,null,text);
w.nextMatch = lookaheadRegExp.lastIndex;
}
};
// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
createTiddlyElement(place,"br");
};
// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
var i = this.indexOf(item);
return i == -1 ? null : i;
};
// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
return store.getLoader().internalizeTiddler(store,this,title,divRef);
};
// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
return store.getSaver().externalizeTiddler(store,this);
};
// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
return store.allTiddlersAsHtml();
}
// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
refreshPageTemplate(title);
}
// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
story.displayTiddlers(srcElement,titles,template,animate);
}
// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
story.displayTiddler(srcElement,title,template,animate);
}
// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;
// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");
}
//}}}
/***
|''Name:''|DoBackupMacro|
|''Version:''|2.0 (9-Apr-2006)|
|''Author:''|[[Jack]]|
|''Type:''|Macro|
!Description
Creates a button which allows you to backup your TiddlyWiki on demand.
!Usage
Add the following command to your SideBarOptions tiddler:
{{{<<doBackup>>}}}
!Revision History
* Original by [[Jack]] 9-Apr-2006
!To Do
* List non-explicit links (e.g. from tagging macro)
!Code
***/
//{{{
version.extensions.doBackup= {major: 2, minor: 0, revision: 0, date: new Date("Apr 9, 2006")};
config.macros.doBackup={label: "backup", prompt: "Backup this TiddlyWiki"}
config.macros.doBackup.handler = function(place)
{
if(!readOnly)
createTiddlyButton(place,this.label,this.prompt,function ()
{doBackup(); return false;},null,null,this.accessKey);
}
doBackup = function() {
var optSaveBackups = config.options.chkSaveBackups
config.options.chkSaveBackups = true
saveChanges()
config.options.chkSaveBackups = optSaveBackups
}
//}}}
<<forEachTiddler where 'tiddler.tags.contains("E-mails")' sortBy 'tiddler.title'>>
<script label="edit a tiddler">
var title=prompt("Enter the title of a tiddler to edit (case sensitive)");
while (title && title.length && !store.tiddlerExists(title)) {
displayMessage("The tiddler '%0' doesn't exist".format([title]));
var title=prompt("Please enter a tiddler title",title);
}
if (!title||!title.length) return; /* cancelled by user */
story.displayTiddler(null,title,2);
</script>
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div macro='tiddler QuickEditToolbar'></div>
<div class='editor' macro='edit tags'></div>
<div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div macro='showWhen tiddler.tags.contains("Topics") || tiddler.title =="Enter the name for your new master topic here"'>[[TopicNote]]</div>
<div macro='showWhen tiddler.tags.contains("Note") || tiddler.title =="New Note"'>[[NoteNote]]</div>
<div class='editor' macro='edit text'></div>
<!--}}}-->
@@color:#C06;''» »'' @@ Tabs excluded From Lists
----
<script>
// get all tiddlers tagged with "excludeLists"
var tids=store.getTaggedTiddlers("excludeLists");
// keep only tiddlers *also* tagged with New
var list=[];
for (var t=0; t<tids.length; t++)
if (tids[t].isTagged("excludeLists")) list.push(tids[t]);
// create output list of tiddler titles, one per line
var out="";
for (var t=0; t<list.length; t++) out+="#[["+list[t].title+"]]\n";
return out;
</script>
@@color:#C06;''» »'' @@ Tabs excluded from searches.
----
<script>
// get all tiddlers tagged with "excludeSearch"
var tids=store.getTaggedTiddlers("excludeSearch");
// keep only tiddlers *also* tagged with New
var list=[];
for (var t=0; t<tids.length; t++)
if (tids[t].isTagged("excludeSearch")) list.push(tids[t]);
// create output list of tiddler titles, one per line
var out="";
for (var t=0; t<list.length; t++) out+="#[["+list[t].title+"]]\n";
return out;
</script>
/***
|Name:|ExtentTagButtonPlugin|
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
window.onClickTag_mptw_orig.apply(this,arguments);
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
// Thanks Saq, you're a genius :)
var popup = Popup.stack[Popup.stack.length-1].popup;
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
return false;
}
//}}}
@@color:#C06;''» »'' @@ <<tiddler EditATiddler>>
----
|>|<<search>>|
|<<option chkSearchTitles>> Titles <<option chkSearchText>> Text <<option chkSearchTags>>Tags<<option chkHoldSearches>> Hold |
|borderlessL|k
----
|>|@@color:#04b;font-weight:bold;goto ''» »'' @@<<gotoTiddler>>|
|borderlessL|k
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|© 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description
Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.
''Syntax:''
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].
!Revision history
* v1.0.8 (2007-04-12)
** Adapted to latest TiddlyWiki 2.2 Beta importTiddlyWiki API (introduced with changeset 2004). TiddlyWiki 2.2 Beta builds prior to changeset 2004 are no longer supported (but TiddlyWiki 2.1 and earlier, of cause)
* v1.0.7 (2007-03-28)
** Also support "pre" formatted TiddlyWikis (introduced with TW 2.2) (when using "in" clause to work on external tiddlers)
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features:
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen)
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features:
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs:
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features:
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// ForEachTiddlerPlugin
//============================================================================
//============================================================================
// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {
if (!window.abego) window.abego = {};
version.extensions.ForEachTiddlerPlugin = {
major: 1, minor: 0, revision: 8,
date: new Date(2007,3,12),
source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};
// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
TiddlyWiki.prototype.forEachTiddler = function(callback) {
for(var t in this.tiddlers) {
callback.call(this,t,this.tiddlers[t]);
}
};
}
//============================================================================
// forEachTiddler Macro
//============================================================================
version.extensions.forEachTiddler = {
major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
config.macros.forEachTiddler = {
// Standard Properties
label: "forEachTiddler",
prompt: "Perform actions on a (sorted) selection of tiddlers",
// actions
actions: {
addToList: {},
write: {}
}
};
// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler
// ---------------------------------------------------------------------------
config.macros.forEachTiddler.getContainingTiddler = function(e) {
while(e && !hasClass(e,"tiddler"))
e = e.parentNode;
var title = e ? e.getAttribute("tiddler") : null;
return title ? store.getTiddler(title) : null;
};
config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);
if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the "in" clause
var tiddlyWikiPath = undefined;
if ((i < params.length) && params[i] == "in") {
i++;
if (i >= params.length) {
this.handleError(place, "TiddlyWiki path expected behind 'in'.");
return;
}
tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the where clause
var whereClause ="true";
if ((i < params.length) && params[i] == "where") {
i++;
whereClause = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the sort stuff
var sortClause = null;
var sortAscending = true;
if ((i < params.length) && params[i] == "sortBy") {
i++;
if (i >= params.length) {
this.handleError(place, "sortClause missing behind 'sortBy'.");
return;
}
sortClause = this.paramEncode(params[i]);
i++;
if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
sortAscending = params[i] == "ascending";
i++;
}
}
// Parse the script
var scriptText = null;
if ((i < params.length) && params[i] == "script") {
i++;
scriptText = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the action.
// When we are already at the end use the default action
var actionName = "addToList";
if (i < params.length) {
if (!config.macros.forEachTiddler.actions[params[i]]) {
this.handleError(place, "Unknown action '"+params[i]+"'.");
return;
} else {
actionName = params[i];
i++;
}
}
// Get the action parameter
// (the parsing is done inside the individual action implementation.)
var actionParameter = params.slice(i);
// --- Processing ------------------------------------------
try {
this.performMacro({
place: place,
inTiddler: tiddler,
whereClause: whereClause,
sortClause: sortClause,
sortAscending: sortAscending,
actionName: actionName,
actionParameter: actionParameter,
scriptText: scriptText,
tiddlyWikiPath: tiddlyWikiPath});
} catch (e) {
this.handleError(place, e);
}
};
// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {
var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);
var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
context["tiddlyWiki"] = tiddlyWiki;
// Get the tiddlers, as defined by the whereClause
var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
context["tiddlers"] = tiddlers;
// Sort the tiddlers, when sorting is required.
if (parameter.sortClause) {
this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
}
return {tiddlers: tiddlers, context: context};
};
// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
return this.getTiddlersAndContext(parameter).tiddlers;
};
// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
//
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
//
// All properties are optional.
// For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
var tiddlersAndContext = this.getTiddlersAndContext(parameter);
// Perform the action
var actionName = parameter.actionName ? parameter.actionName : "addToList";
var action = config.macros.forEachTiddler.actions[actionName];
if (!action) {
this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
return;
}
var actionHandler = action.handler;
actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};
// ---------------------------------------------------------------------------
// The actions
// ---------------------------------------------------------------------------
// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
return;
}
// Perform the action.
var list = document.createElement("ul");
place.appendChild(list);
for (var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var listItem = document.createElement("li");
list.appendChild(listItem);
createTiddlyLink(listItem, tiddler.title, true);
}
};
abego.parseNamedParameter = function(name, parameter, i) {
var beginExpression = null;
if ((i < parameter.length) && parameter[i] == name) {
i++;
if (i >= parameter.length) {
throw "Missing text behind '%0'".format([name]);
}
return config.macros.forEachTiddler.paramEncode(parameter[i]);
}
return null;
}
// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
if (p >= parameter.length) {
this.handleError(place, "Missing expression behind 'write'.");
return;
}
var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
// Parse the "begin" option
var beginExpression = abego.parseNamedParameter("begin", parameter, p);
if (beginExpression !== null)
p += 2;
var endExpression = abego.parseNamedParameter("end", parameter, p);
if (endExpression !== null)
p += 2;
var noneExpression = abego.parseNamedParameter("none", parameter, p);
if (noneExpression !== null)
p += 2;
// Parse the "toFile" option
var filename = null;
var lineSeparator = undefined;
if ((p < parameter.length) && parameter[p] == "toFile") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
return;
}
filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
p++;
if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
return;
}
lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
}
}
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
return;
}
// Perform the action.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
var count = tiddlers.length;
var text = "";
if (count > 0 && beginExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
for (var i = 0; i < count; i++) {
var tiddler = tiddlers[i];
text += func(tiddler, context, count, i);
}
if (count > 0 && endExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);
if (count == 0 && noneExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
if (filename) {
if (lineSeparator !== undefined) {
lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
text = text.replace(/\n/mg,lineSeparator);
}
saveFile(filename, convertUnicodeToUTF8(text));
} else {
var wrapper = createTiddlyElement(place, "span");
wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
}
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
return {
place : placeParam,
whereClause : whereClauseParam,
sortClause : sortClauseParam,
sortAscending : sortAscendingParam,
script : scriptText,
actionName : actionNameParam,
actionParameter : actionParameterParam,
tiddlyWikiPath : tiddlyWikiPathParam,
inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
};
};
// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
if (!idPrefix) {
idPrefix = "store";
}
var lenPrefix = idPrefix.length;
// Read the content of the given file
var content = loadFile(this.getLocalPath(path));
if(content === null) {
throw "TiddlyWiki '"+path+"' not found.";
}
var tiddlyWiki = new TiddlyWiki();
// Starting with TW 2.2 there is a helper function to import the tiddlers
if (tiddlyWiki.importTiddlyWiki) {
if (!tiddlyWiki.importTiddlyWiki(content))
throw "File '"+path+"' is not a TiddlyWiki.";
tiddlyWiki.dirty = false;
return tiddlyWiki;
}
// The legacy code, for TW < 2.2
// Locate the storeArea div's
var posOpeningDiv = content.indexOf(startSaveArea);
var posClosingDiv = content.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
throw "File '"+path+"' is not a TiddlyWiki.";
}
var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
// Create a "div" element that contains the storage text
var myStorageDiv = document.createElement("div");
myStorageDiv.innerHTML = storageText;
myStorageDiv.normalize();
// Create all tiddlers in a new TiddlyWiki
// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
var store = myStorageDiv.childNodes;
for(var t = 0; t < store.length; t++) {
var e = store[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
title = e.id.substr(lenPrefix);
if(title && title !== "") {
var tiddler = tiddlyWiki.createTiddler(title);
tiddler.loadFromDiv(e,title);
}
}
tiddlyWiki.dirty = false;
return tiddlyWiki;
};
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
//
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
var script = context["script"];
var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
var fullText = (script ? script+";" : "")+functionText+";theFunction;";
return eval(fullText);
};
// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
var result = [];
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
tiddlyWiki.forEachTiddler(function(title,tiddler) {
if (func(tiddler, context, undefined, undefined)) {
result.push(tiddler);
}
});
return result;
};
// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
var message = "Extra parameter behind '"+actionName+"':";
for (var i = firstUnusedIndex; i < parameter.length; i++) {
message += " "+parameter[i];
}
this.handleError(place, message);
};
// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? -1
: +1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? +1
: -1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
// To avoid evaluating the sortClause whenever two items are compared
// we pre-calculate the sortValue for every item in the array and store it in a
// temporary property ("forEachTiddlerSortValue") of the tiddlers.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
var count = tiddlers.length;
var i;
for (i = 0; i < count; i++) {
var tiddler = tiddlers[i];
tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
}
// Do the sorting
tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);
// Delete the temporary property that holds the sortValue.
for (i = 0; i < tiddlers.length; i++) {
delete tiddlers[i].forEachTiddlerSortValue;
}
};
// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
displayMessage(message);
};
// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
var message ="<<"+macroName;
for (var i = 0; i < params.length; i++) {
message += " "+params[i];
}
message += ">>";
displayMessage(message);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};
// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
if (place) {
this.createErrorElement(place, exception);
} else {
throw exception;
}
};
// Internal.
//
// Encodes the given string.
//
// Replaces
// "$))" to ">>"
// "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
var reGTGT = new RegExp("\\$\\)\\)","mg");
var reGT = new RegExp("\\$\\)","mg");
return s.replace(reGTGT, ">>").replace(reGT, ">");
};
// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
//
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
// Remove any location part of the URL
var hashPos = originalPath.indexOf("#");
if(hashPos != -1)
originalPath = originalPath.substr(0,hashPos);
// Convert to a native file format assuming
// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
var localPath;
if(originalPath.charAt(9) == ":") // pc local file
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(7));
else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(5));
else // pc network file
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
return localPath;
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
"forEachTiddler");
//============================================================================
// End of forEachTiddler Macro
//============================================================================
//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
var n = prefix.length;
return (this.length >= n) && (this.slice(0, n) == prefix);
};
//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
var n = suffix.length;
return (this.length >= n) && (this.right(n) == suffix);
};
//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
return this.indexOf(substring) >= 0;
};
//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] == item) {
return i;
}
}
return -1;
};
//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false.
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
return (this.indexOf(item) >= 0);
};
//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
for(var i = 0; i < items.length; i++) {
if (this.contains(items[i])) {
return true;
}
}
return false;
};
//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
//
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null]
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
for(var i = 0; i < items.length; i++) {
if (!this.contains(items[i])) {
return false;
}
}
return true;
};
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink,
displayMessage, endSaveArea, hasClass, loadFile, saveFile,
startSaveArea, store, wikify */
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
The {{{<<formTiddler ...>>}}} macro defined by the FormTiddlerPlugin.
When a tiddler T1 references the (FormTemplate) tiddler T2 in the FormTiddlerMacro, the data of T1 can be edited through the INPUT elements defined by T2.
/***
<<checkForDataTiddlerPlugin>>
|''Name:''|FormTiddlerPlugin|
|''Version:''|1.0.6 (2007-06-24)|
|''Source:''|http://tiddlywiki.abego-software.de/#FormTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|formTiddler, checkForDataTiddlerPlugin, newTiddlerWithForm|
|''Requires:''|DataTiddlerPlugin|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Use form-based tiddlers to enter your tiddler data using text fields, listboxes, checkboxes etc. (All standard HTML Form input elements supported).
''Syntax:''
|>|{{{<<}}}''formTiddler'' //tiddlerName//{{{>>}}}|
|//tiddlerName//|The name of the FormTemplate tiddler to be used to edit the data of the tiddler containing the macro.|
|>|{{{<<}}}''newTiddlerWithForm'' //formTemplateName// //buttonLabel// [//titleExpression// [''askUser'']] {{{>>}}}|
|//formTemplateName//|The name of the tiddler that defines the form the new tiddler should use.|
|//buttonLabel//|The label of the button|
|//titleExpression//|A (quoted) JavaScript String expression that defines the title (/name) of the new tiddler.|
|''askUser''|Typically the user is not asked for the title when a title is specified (and not yet used). When ''askUser'' is given the user will be asked in any case. This may be used when the calculated title is just a suggestion that must be confirmed by the user|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
For details and how to use the macros see the [[introduction|FormTiddler Introduction]] and the [[examples|FormTiddler Examples]].
!Revision history
* v1.0.6 (2007-06-24)
** Fixed problem when using SELECT component in Internet Explorer (thanks to MaikBoenig for reporting)
* v1.0.5 (2006-02-24)
** Removed "debugger;" instruction
* v1.0.4 (2006-02-07)
** Bug: On IE no data is written to data section when field values changed (thanks to KenGirard for reporting)
* v1.0.3 (2006-02-05)
** Bug: {{{"No form template specified in <<formTiddler>>"}}} when using formTiddler macro on InternetExplorer (thanks to KenGirard for reporting)
* v1.0.2 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.1 (2005-12-22)
** Features:
*** Support InternetExplorer
*** Added newTiddlerWithForm Macro
* v1.0.0 (2005-12-14)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// FormTiddlerPlugin
//============================================================================
//============================================================================
if (!window.abego) window.abego = {};
abego.getOptionsValue = function(element,i) {
var v = element.options[i].value;
if (!v && element.options[i].text)
v = element.options[i].text;
return v;
};
version.extensions.FormTiddlerPlugin = {
major: 1, minor: 0, revision: 5,
date: new Date(2006, 2, 24),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#FormTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; }
//============================================================================
// formTiddler Macro
//============================================================================
// -------------------------------------------------------------------------------
// Configurations and constants
// -------------------------------------------------------------------------------
config.macros.formTiddler = {
// Standard Properties
label: "formTiddler",
version: {major: 1, minor: 0, revision: 4, date: new Date(2006, 2, 7)},
prompt: "Edit tiddler data using forms",
// Define the "setters" that set the values of INPUT elements of a given type
// (must match the corresponding "getter")
setter: {
button: function(e, value) {/*contains no data */ },
checkbox: function(e, value) {e.checked = value;},
file: function(e, value) {try {e.value = value;} catch(e) {/* ignore, possibly security error*/}},
hidden: function(e, value) {e.value = value;},
password: function(e, value) {e.value = value;},
radio: function(e, value) {e.checked = (e.value == value);},
reset: function(e, value) {/*contains no data */ },
"select-one": function(e, value) {config.macros.formTiddler.setSelectOneValue(e,value);},
"select-multiple": function(e, value) {config.macros.formTiddler.setSelectMultipleValue(e,value);},
submit: function(e, value) {/*contains no data */},
text: function(e, value) {e.value = value;},
textarea: function(e, value) {e.value = value;}
},
// Define the "getters" that return the value of INPUT elements of a given type
// Return undefined to not store any data.
getter: {
button: function(e, value) {return undefined;},
checkbox: function(e, value) {return e.checked;},
file: function(e, value) {return e.value;},
hidden: function(e, value) {return e.value;},
password: function(e, value) {return e.value;},
radio: function(e, value) {return e.checked ? e.value : undefined;},
reset: function(e, value) {return undefined;},
"select-one": function(e, value) {return config.macros.formTiddler.getSelectOneValue(e);},
"select-multiple": function(e, value) {return config.macros.formTiddler.getSelectMultipleValue(e);},
submit: function(e, value) {return undefined;},
text: function(e, value) {return e.value;},
textarea: function(e, value) {return e.value;}
}
};
// -------------------------------------------------------------------------------
// The formTiddler Macro Handler
// -------------------------------------------------------------------------------
config.macros.formTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
if (!config.macros.formTiddler.checkForExtensions(place, macroName)) {
return;
}
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// get the name of the form template tiddler
var formTemplateName = undefined;
if (i < params.length) {
formTemplateName = params[i];
i++;
}
if (!formTemplateName) {
config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
return;
}
// --- Processing ------------------------------------------
// Get the form template text.
// (This contains the INPUT elements for the form.)
var formTemplateTiddler = store.getTiddler(formTemplateName);
if (!formTemplateTiddler) {
config.macros.formTiddler.createErrorElement(place, "Form template '" + formTemplateName + "' not found.");
return;
}
var templateText = formTemplateTiddler.text;
if(!templateText) {
// Shortcut: when template text is empty we do nothing.
return;
}
// Get the name of the tiddler containing this "formTiddler" macro
// (i.e. the tiddler, that will be edited and that contains the data)
var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(place);
// Append a "form" element.
var formName = "form"+formTemplateName+"__"+tiddlerName;
var e = document.createElement("form");
e.setAttribute("name", formName);
place.appendChild(e);
// "Embed" the elements defined by the templateText (i.e. the INPUT elements)
// into the "form" element we just created
wikify(templateText, e);
// Initialize the INPUT elements.
config.macros.formTiddler.initValuesAndHandlersInFormElements(formName, DataTiddler.getDataObject(tiddlerName));
}
// -------------------------------------------------------------------------------
// Form Data Access
// -------------------------------------------------------------------------------
// Internal.
//
// Initialize the INPUT elements of the form with the values of their "matching"
// data fields in the tiddler. Also setup the onChange handler to ensure that
// changes in the INPUT elements are stored in the tiddler's data.
//
config.macros.formTiddler.initValuesAndHandlersInFormElements = function(formName, data) {
// config.macros.formTiddler.trace("initValuesAndHandlersInFormElements(formName="+formName+", data="+data+")");
// find the form
var form = config.macros.formTiddler.findForm(formName);
if (!form) {
return;
}
try {
var elems = form.elements;
for (var i = 0; i < elems.length; i++) {
var c = elems[i];
var setter = config.macros.formTiddler.setter[c.type];
if (setter) {
var value = data[c.name];
if (value != null) {
setter(c, value);
}
c.onchange = onFormTiddlerChange;
} else {
config.macros.formTiddler.displayFormTiddlerError("No setter defined for INPUT element of type '"+c.type+"'. (Element '"+c.name+"' in form '"+formName+"')");
}
}
} catch(e) {
config.macros.formTiddler.displayFormTiddlerError("Error when updating elements with new formData. "+e);
}
}
// Internal.
//
// @return [may be null]
//
config.macros.formTiddler.findForm = function(formName) {
// We must manually iterate through the document's forms, since
// IE does not support the "document[formName]" approach
var forms = window.document.forms;
for (var i = 0; i < forms.length; i++) {
var form = forms[i];
if (form.name == formName) {
return form;
}
}
return null;
}
// Internal.
//
config.macros.formTiddler.setSelectOneValue = function(element,value) {
var n = element.options.length;
for (var i = 0; i < n; i++) {
element.options[i].selected = abego.getOptionsValue(element,i) == value;
}
}
// Internal.
//
config.macros.formTiddler.setSelectMultipleValue = function(element,value) {
var values = {};
for (var i = 0; i < value.length; i++) {
values[value[i]] = true;
}
var n = element.length;
for (var i = 0; i < n; i++) {
element.options[i].selected = !(!values[abego.getOptionsValue(element,i)]);
}
}
// Internal.
//
config.macros.formTiddler.getSelectOneValue = function(element) {
var i = element.selectedIndex;
return (i >= 0) ? abego.getOptionsValue(element,i) : null;
}
// Internal.
//
config.macros.formTiddler.getSelectMultipleValue = function(element) {
var values = [];
var n = element.length;
for (var i = 0; i < n; i++) {
if (element.options[i].selected) {
values.push(abego.getOptionsValue(element,i));
}
}
return values;
}
// -------------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------------
// Internal.
//
config.macros.formTiddler.checkForExtensions = function(place,macroName) {
if (!version.extensions.DataTiddlerPlugin) {
config.macros.formTiddler.createErrorElement(place, "<<" + macroName + ">> requires the DataTiddlerPlugin. (You can get it from http://tiddlywiki.abego-software.de/#DataTiddlerPlugin)");
return false;
}
return true;
}
// Internal.
//
// Displays a trace message in the "TiddlyWiki" message pane.
// (used for debugging)
//
config.macros.formTiddler.trace = function(s) {
displayMessage("Trace: "+s);
}
// Internal.
//
// Display some error message in the "TiddlyWiki" message pane.
//
config.macros.formTiddler.displayFormTiddlerError = function(s) {
alert("FormTiddlerPlugin Error: "+s);
}
// Internal.
//
// Creates an element that holds an error message
//
config.macros.formTiddler.createErrorElement = function(place, message) {
return createTiddlyElement(place,"span",null,"formTiddlerError",message);
}
// Internal.
//
// Returns the name of the tiddler containing the given element.
//
config.macros.formTiddler.getContainingTiddlerName = function(element) {
return story.findContainingTiddler(element).id.substr(7);
}
// -------------------------------------------------------------------------------
// Event Handlers
// -------------------------------------------------------------------------------
// This function must be called by the INPUT elements whenever their
// data changes. Typically this is done through an "onChange" handler.
//
function onFormTiddlerChange (e) {
// config.macros.formTiddler.trace("onFormTiddlerChange "+e);
if (!e) var e = window.event;
var target = resolveTarget(e);
var tiddlerName = config.macros.formTiddler.getContainingTiddlerName(target);
var getter = config.macros.formTiddler.getter[target.type];
if (getter) {
var value = getter(target);
DataTiddler.setData(tiddlerName, target.name, value);
} else {
config.macros.formTiddler.displayFormTiddlerError("No getter defined for INPUT element of type '"+target.type+"'. (Element '"+target.name+"' used in tiddler '"+tiddlerName+"')");
}
}
// ensure that the function can be used in HTML event handler
window.onFormTiddlerChange = onFormTiddlerChange;
// -------------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// -------------------------------------------------------------------------------
setStylesheet(
".formTiddlerError{color: #ffffff;background-color: #880000;}",
"formTiddler");
//============================================================================
// checkForDataTiddlerPlugin Macro
//============================================================================
config.macros.checkForDataTiddlerPlugin = {
// Standard Properties
label: "checkForDataTiddlerPlugin",
version: {major: 1, minor: 0, revision: 0, date: new Date(2005, 12, 14)},
prompt: "Check if the DataTiddlerPlugin exists"
}
config.macros.checkForDataTiddlerPlugin.handler = function(place,macroName,params) {
config.macros.formTiddler.checkForExtensions(place, config.macros.formTiddler.label);
}
//============================================================================
// newTiddlerWithForm Macro
//============================================================================
config.macros.newTiddlerWithForm = {
// Standard Properties
label: "newTiddlerWithForm",
version: {major: 1, minor: 0, revision: 1, date: new Date(2006, 1, 6)},
prompt: "Creates a new Tiddler with a <<formTiddler ...>> macro"
}
config.macros.newTiddlerWithForm.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// get the name of the form template tiddler
var formTemplateName = undefined;
if (i < params.length) {
formTemplateName = params[i];
i++;
}
if (!formTemplateName) {
config.macros.formTiddler.createErrorElement(place, "No form template specified in <<" + macroName + ">>.");
return;
}
// get the button label
var buttonLabel = undefined;
if (i < params.length) {
buttonLabel = params[i];
i++;
}
if (!buttonLabel) {
config.macros.formTiddler.createErrorElement(place, "No button label specified in <<" + macroName + ">>.");
return;
}
// get the (optional) tiddlerName script and "askUser"
var tiddlerNameScript = undefined;
var askUser = false;
if (i < params.length) {
tiddlerNameScript = params[i];
i++;
if (i < params.length && params[i] == "askUser") {
askUser = true;
i++;
}
}
// --- Processing ------------------------------------------
if(!readOnly) {
var onClick = function() {
var tiddlerName;
if (tiddlerNameScript) {
try {
tiddlerName = eval(tiddlerNameScript);
} catch (ex) {
}
}
if (!tiddlerName || askUser) {
tiddlerName = prompt("Please specify a tiddler name.", askUser ? tiddlerName : "");
}
while (tiddlerName && store.getTiddler(tiddlerName)) {
tiddlerName = prompt("A tiddler named '"+tiddlerName+"' already exists.\n\n"+"Please specify a tiddler name.", tiddlerName);
}
// tiddlerName is either null (user canceled) or a name that is not yet in the store.
if (tiddlerName) {
var body = "<<formTiddler [["+formTemplateName+"]]>>";
var tags = [];
store.saveTiddler(tiddlerName,tiddlerName,body,config.options.txtUserName,new Date(),tags);
story.displayTiddler(null,tiddlerName,1);
}
}
createTiddlyButton(place,buttonLabel,buttonLabel,onClick);
}
}
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
<<forEachTiddler where 'tiddler.tags.contains("Free time")' sortBy 'tiddler.title'>>
<<siteMap [[Enter the name for your new goal here, too]] . sliders>>
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span style="padding-right:0em;" macro='tagger'></span><span class='newbutton' style='padding-right: 0.5em;' macro='newHere title:"Enter the name for your new task here" label:"*New task for this goal*" tag:"task" text:{{store.getTiddlerText("TaskSliderFrame")}}'></span></div>
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
The philosophy behind ~TiddlyDu3 is that everyone has major life goals ("Be a good husband and father", "Keep everything functioning"). To reach each goal, we undertake tasks. And some of these tasks are projects - series of multiple tasks. ~TiddlyDu3 helps you create and index your goals, projects and tasks with ease.
We recommend taking some time to define your personal life goals, then creating a tiddler for each goal using the New goal button in the Tasks tab. Within each goal tiddler you can use the buttons in the toolbar to create projects and tasks that help you reach that goal. Within each project tiddler you can use the toolbar buttons to create tasks that help you finish that project.
As you add projects and tasks to your goals, and tasks to your projects, they will automatically be added to expandable/collapsible hierarchical menus in the Goals tab and the Projects tab. Refresh the menu to see the new additions. Then when you want to review your goals and projects, you need only to open these tabs and expand the menus.
//''Important note'': in order for all items to appear in the expandable menus, you must copy the title you give your tiddler, and paste it between the brackets in the slider menu as you create the tiddler.//
/***
|Name|GotoPlugin|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|view any tiddler by entering it's title - displays list of possible matches|
''View a tiddler by typing its title and pressing //enter//.'' As you type, a list of possible matches is displayed. You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press //escape// to close the listbox to resume typing. When the listbox is ''//not//'' being displayed, press //escape// to clear the current text input and start over.
!!!!!Documentation
>see [[GotoPluginInfo]]
!!!!!Revisions
<<<
2008.10.16 [1.7.0] in macro handler(), changed to use //named// params instead of positional params, and added optional "filter:" param for tag filtering. Removed 'insert' handling (now provided by [[QuickEditPlugin]]).
|please see [[GotoPluginInfo]] for additional revision details|
2006.05.05 [0.0.0] started
<<<
!!!!!Code
***/
//{{{
version.extensions.GotoPlugin= {major: 1, minor: 7, revision: 0, date: new Date(2008,10,16)};
// automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");
config.macros.gotoTiddler= {
listMaxSize: 10,
listHeading: 'Found %0 matching title%1...',
searchItem: "Search for '%0'...",
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
var quiet =params.contains("quiet");
var search =params.contains("search");
params = paramString.parseParams("anon",null,true,false,false);
var instyle =getParam(params,"inputstyle","");
var liststyle =getParam(params,"liststyle","");
var filter =getParam(params,"filter","");
var html=this.html;
var keyevent=window.event?"onkeydown":"onkeypress"; // IE event fixup for ESC handling
html=html.replace(/%keyevent%/g,keyevent);
html=html.replace(/%search%/g,search);
html=html.replace(/%quiet%/g,quiet);
html=html.replace(/%instyle%/g,instyle);
html=html.replace(/%liststyle%/g,liststyle);
html=html.replace(/%filter%/g,filter);
if (config.browser.isIE) html=this.IEtableFixup.format([html]);
createTiddlyElement(place,"span").innerHTML=html;
},
html:
'<form onsubmit="return false" style="display:inline;margin:0;padding:0">\
<input name=gotoTiddler type=text autocomplete="off" accesskey="G" style="%instyle%"\
title="enter a tiddler title"\
onclick="this.form.list.style.display=\'none\';"\
onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list);"\
onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,%quiet%,%search%);">\
<select name=list style="%liststyle%;display:none;position:absolute"\
onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
onblur="this.style.display=\'none\';"\
%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler);"\
onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this);">\
</select><input name="filter" type="hidden" value="%filter%">\
</form>',
IEtableFixup:
"<table style='width:100%;display:inline;padding:0;margin:0;border:0;'>\
<tr style='padding:0;margin:0;border:0;'><td style='padding:0;margin:0;border:0;'>\
%0</td></tr></table>",
getItems:
function(val,filter) {
if (!this.items.length || val.length<2) { // starting new search, refresh cached list of tiddlers/shadows/tags
this.items=new Array();
if (filter.length) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var tiddlers=store.sortTiddlers(fn.apply(store,[filter]),'title');
} else
var tiddlers=store.getTiddlers("title","excludeLists");
for(var t=0; t<tiddlers.length; t++) this.items.push(tiddlers[t].title);
if (!filter.length) {
for (var t in config.shadowTiddlers) this.items.pushUnique(t);
var tags=store.getTags();
for(var t=0; t<tags.length; t++) this.items.pushUnique(tags[t][0]);
}
}
var found = [];
var match=val.toLowerCase();
for(var i=0; i<this.items.length; i++)
if (this.items[i].toLowerCase().indexOf(match)!=-1) found.push(this.items[i]);
return found;
},
items: [], // cached list of tiddlers/shadows/tags
getItemSuffix:
function(t) {
if (store.tiddlerExists(t)) return ""; // tiddler
if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
return " (tag)"; // tag
},
keyProcessed:
function(ev) { // utility function: exits handler and prevents browser from processing the keystroke
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;
},
inputEscKeyHandler:
function(event,here,list) {
var key=event.keyCode;
// escape... hide list (2nd esc=clears input)
if (key==27) {
if (list.style.display=="none")
here.value=here.defaultValue;
list.style.display="none";
return this.keyProcessed(event);
}
return true; // key bubbles up
},
inputKeyHandler:
function(event,here,quiet,search) {
var key=event.keyCode;
var list=here.form.list;
var filter=here.form.filter;
// non-printing chars... bubble up, except: backspace=8, enter=13, space=32, down=40, delete=46
if (key<48) switch(key) { case 8: case 13: case 32: case 40: case 46: break; default: return true; }
// blank input... if down/enter... fall through (list all)... else, and hide list
if (!here.value.length && !(key==40 || key==13)) { list.style.display="none"; return this.keyProcessed(event); }
// make sure list is shown (unless quiet option)
list.style.display=!quiet?"block":"none";
// non-blank input... enter key... show/create tiddler
if (key==13) return this.processItem(here.value,here,list);
// down key... shows/moves to list...
if (key==40) { list.style.display="block"; list.focus(); }
// if list is showing, fill it with found results...
if (list.style.display!="none") {
var indent='\xa0\xa0\xa0';
var found = this.getItems(here.value,filter.value); // find matching items...
found.sort(); // alpha by title
while (list.length > 0) list.options[0]=null; // clear list
var hdr=this.listHeading.format([found.length,found.length==1?"":"s"]);
list.options[0]=new Option(hdr,"",false,false);
for (var t=0; t<found.length; t++) list.options[list.length]=
new Option(indent+found[t]+this.getItemSuffix(found[t]),found[t],false,false);
if (search)
list.options[list.length]=new Option(this.searchItem.format([here.value]),"*",false,false);
list.size=(list.length<this.listMaxSize?list.length:this.listMaxSize); // resize list...
list.selectedIndex=(key==40 || key==13)?1:0;
}
return true; // key bubbles up
},
selectKeyHandler:
function(event,list,editfield) {
if (event.keyCode==27) // escape... hide list, move to edit field
{ editfield.focus(); list.style.display="none"; return this.keyProcessed(event); }
if (event.keyCode==13 && list.value.length) // enter... view selected item
{ this.processItem(list.value,editfield,list); return this.keyProcessed(event); }
return true; // key bubbles up
},
processItem:
function(title,here,list) {
if (!title.length) return;
list.style.display='none';
if (title=="*") { story.search(here.value); return false; } // do full-text search
here.value=title;
story.displayTiddler(null,title); // show selected tiddler
return false;
}
}
//}}}
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.2.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The ~HTMLFormatting plugin allows you to ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2008.09.19 [2.2.0] in wikifyTextNodes(), don't wikify the contents of STYLE nodes (thanks to MorrisGray for bug report)
| see [[HTMLFormattingPluginInfo]] for additional revision details |
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormattingPlugin= {major: 2, minor: 2, revision: 0, date: new Date(2008,9,19)};
// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
if (i<config.formatters.length) config.formatters[i].handler=function(w) {
if (!this.lookaheadRegExp) // fixup for TW2.0.x
this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var html=lookaheadMatch[1];
// if <hide linebreaks> is present, suppress wiki-style literal handling of newlines
if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
// remove all \r's added by IE textarea and mask newlines and macro brackets
html=html.replace(/\r/g,'').replace(/\n/g,'\\n').replace(/<</g,'%%(').replace(/>>/g,')%%');
// create span, let browser parse HTML
var e=createTiddlyElement(w.output,"span"); e.innerHTML=html;
// re-render text nodes as wiki-formatted content
wikifyTextNodes(e);
// continue parsing
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
}
// wikify text nodes remaining after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode)
{
function unmask(s) { return s.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n'); }
switch (theNode.nodeName.toLowerCase()) {
case 'style': case 'option': case 'select':
theNode.innerHTML=unmask(theNode.innerHTML);
break;
case 'textarea':
theNode.value=unmask(theNode.value);
break;
case '#text':
var txt=unmask(theNode.nodeValue);
var newNode=createTiddlyElement(null,"span");
theNode.parentNode.replaceChild(newNode,theNode);
wikify(txt,newNode);
break;
default:
for (var i=0;i<theNode.childNodes.length;i++)
wikifyTextNodes(theNode.childNodes.item(i)); // recursion
break;
}
}
//}}}
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.hideWhenLastTest = false;
window.removeElementWhen = function(test,place) {
window.hideWhenLastTest = test;
if (test) {
removeChildren(place);
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}},
hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title == params[0], place);
}},
showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title != params[0], place);
}},
'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !window.hideWhenLastTest, place);
}}
});
//}}}
Do you like ''~TiddlyDu3''? If so, here's how you can help us:
* [[Visit our site|http://www.giffmex.org]]
* [[Learn about the missions agency we belong to, CRWM|http://www.crcna.org/pages/crwm.cfm]]
* [[Donate to CRWM|http://www.crcna.org/pages/crwm_donate_online.cfm]]
* [[Our Amazon wishlist|https://www.amazon.com/gp/registry/wishlist/1OTJM9IE7SPVS/ref=wl_web/]]
* PayPal for our site:<html><form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input name="cmd" type="hidden" value="_s-xclick" /> <input alt="PayPal - The safer, easier way to pay online!" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" type="image" /><img src="https://www.paypal.com/en_US/i/scr/pixel.gif" border="0" alt="" width="1" height="1" />
<input name="encrypted" type="hidden" value="-----BEGIN PKCS7-----MIIHRwYJKoZIhvcNAQcEoIIHODCCBzQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCDOphPrfxixGLSFLAVYRgOAIIMNkhG/fVpBpfPkFZ+/otUKEu2UHrY0szrTCsf73EmPs1hEqXAevosf4f3wmMQGaQ/+dxpooMXJJjv4Y2b74SuehERvjBeBrIOJ6eVVJyTRqTYVACX48cdtp9K8u/qFPEf389dSFw79O0qSSw2YDELMAkGBSsOAwIaBQAwgcQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIvazyO9DMtDGAgaCV7RZqlbC45beBnYKwrZ/t12EFK0DQViCLvSD1OMX0VNiCuXK2lxtlpTzi0ZujHXrRjPZg6zZc5dMsL//Ervy+zUBl6jpsQg5UxqponKYcNnWXjErastgJdYP3Yy5l95L1MwsHnxzhvANg3cIuYhVOsvDNxc933cEdwMSBKI2Q9Kg6oixC49A6FTYW/Xgp2xfdINr7ema6Vgk9V3pge1xjoIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDgwMzIzMTU0MDU4WjAjBgkqhkiG9w0BCQQxFgQUN7zDTYDrAL6cj3fOJ2lKbzKgmcIwDQYJKoZIhvcNAQEBBQAEgYAsUnYV6vvQecisJkhmmfNmG2xemtFm7FfXCJZe+5sNDBiIgy/By44dLPor/j3KAmFsH27u4ORRVGgaYkG0/0Ga7ch1AZaMNCnrXQ8Yw6//ltBN+DPl7RWQ3hbgcPwbVarqkNM67LQ/Scfb22CKMAnKt4vjIeaWAnPySHVsYcqcpg==-----END PKCS7-----" /></form></html>
~IFrames are portals to another webpage or html file (for example, another ~TiddlyWiki file). Here is a [[Sample IFrame|TiddlyWiki Central at giffmex.org]] that opens our index of ~TiddlyWiki resources.
To ''create your own ~IFrame'', just click on 'New ~IFrame' in the ~IFrame tab, replace the text XXXX with the URL of the webpage you wish to access, click 'Done', and your ~IFrame will not only be created but will automatically be added to your ~IFrames index when you refresh.
On Monday, 9 February 2009 2:03:51 PM, YourName imported 1 tiddler from
[[K:\TWNotes\twt-notes.html|K:\TWNotes\twt-notes.html]]:
<<<
#[[DeprecatedFunctionsPlugin]] - skipped after asking
#[[TaggerPlugin]] - added
<<<
----
On Monday, 9 February 2009 6:28:46 AM, YourName imported 150 tiddlers from
[[C:\Users\Morris wa9crd\TiddlyWiki\TWExperiments\Giffmex\tiddlydu3.html|C:\Users\Morris wa9crd\TiddlyWiki\TWExperiments\Giffmex\tiddlydu3.html]]:
<<<
#[[1. Collect your tasks]] - added
#[[18 February 2009]] - added
#[[2. Process your tasks]] - added
#[[2009 calendar]] - added
#[[2010 calendar]] - added
#[[3. Organize]] - added
#[[4. Conduct a weekly review]] - added
#[[5. Do your tasks]] - added
#[[Acknowledgements & license]] - added
#[[Add appointments]] - added
#[[AddActivity]] - added
#[[All appointments]] - added
#[[All e-mails]] - added
#[[All phone#s]] - added
#[[Ask self regularly]] - added
#[[CalendarPlugin]] - added
#[[CalendarPluginConfig]] - added
#[[CalendarYearSliderFrame]] - added
#[[CheckboxPlugin]] - added
#[[Clean, repair]] - added
#[[CloseOnCancelPlugin]] - added
#[[ColorPalette]] - added
#[[Contact groups and contacts]] - added
#[[ContactGroupSliderFrame]] - added
#[[ContactgroupViewTemplate]] - added
#[[Correspondence]] - added
#[[Current]] - added
#[[Data entry]] - added
#[[DataTiddlerPlugin]] - added
#[[DatePickerLibrary]] - added
#[[DatePlugin]] - added
#[[DatePluginConfig]] - added
#[[DefaultTiddlers]] - added
#[[Dennis]] - added
#[[DeprecatedFunctionsPlugin]] - added
#[[DoBackupMacro]] - added
#[[E-mails]] - added
#[[EditTemplate]] - added
#[[Enter the name for your new goal here]] - added
#[[ExcludedFromLists]] - added
#[[ExcludedFromSearches]] - added
#[[ExtendTagButtonPlugin]] - added
#[[ForEachTiddlerPlugin]] - added
#[[FormTiddlerMacro]] - added
#[[FormTiddlerPlugin]] - added
#[[Free time]] - added
#[[GoalSliderFrame]] - added
#[[GoalViewTemplate]] - added
#[[Goals, projects, and tasks]] - added
#[[HTMLFormattingPlugin]] - added
#[[HideWhenPlugin]] - added
#[[How you can help]] - added
#[[IFrames]] - added
#[[Inbox]] - added
#[[InlineJavascriptPlugin]] - added
#[[Investigate, order]] - added
#[[LegacyStrikeThroughPlugin]] - added
#[[MSGray]] - added
#[[MainMenu]] - added
#[[MonkeyTagger]] - added
#[[More info on TiddlyWiki]] - added
#[[Morris]] - added
#[[MorrisBusiness]] - added
#[[MorrisContacts]] - added
#[[My Info]] - added
#[[NestedSlidersPlugin(withGiffmexTweak)]] - added
#[[New piece of info]] - added
#[[NewContactTemplate]] - added
#[[NewHerePlugin(Giffmex version)]] - added
#[[Ongoing]] - added
#[[PageTemplate]] - added
#[[Patrica]] - added
#[[Phone calls]] - added
#[[Plan, organize]] - added
#[[Possibly]] - added
#[[ProjectSliderFrame]] - added
#[[ProjectTemplate]] - added
#[[ProjectViewTemplate]] - added
#[[QuickOpenTagPlugin]] - added
#[[Read]] - added
#[[Refresh]] - added
#[[RefreshCommand]] - added
#[[RefreshTiddlerPlugin]] - added
#[[ReminderMacros]] - added
#[[Removing unwanted features]] - added
#[[Reporting]] - added
#[[SaveCloseTiddlerPlugin]] - added
#[[Schedule]] - added
#[[SearchOptions plugin tweaks]] - added
#[[SearchOptionsPlugin]] - added
#[[SearchOptionsPlugin tweaks]] - added
#[[Shop, out]] - added
#[[SideBarOptions]] - added
#[[SideBarTabs]] - added
#[[SiteMapMacro]] - added
#[[SiteSubtitle]] - added
#[[SiteTitle]] - added
#[[SiteUrl]] - added
#[[SliderSidebarTabs]] - added
#[[Someday/Maybe]] - added
#[[Statuses and tasktypes]] - added
#[[StyleSheet]] - added
#[[StyleSheetOld]] - added
#[[StyleSheetTiddlersBar]] - added
#[[TWHelp-SearchResults]] - added
#[[TabCalendars]] - added
#[[TabContactGroups]] - added
#[[TabContacts]] - added
#[[TabContactsTab]] - added
#[[TabExtras]] - added
#[[TabGTD]] - added
#[[TabGoals]] - added
#[[TabHelp]] - added
#[[TabIFrames]] - added
#[[TabInfo]] - added
#[[TabProjects]] - added
#[[TabTaskTypes]] - added
#[[TabTasks]] - added
#[[TabToDo]] - added
#[[TabsCSS]] - added
#[[TaggedTemplateTweak]] - added
#[[TagglyTaggingPlugin]] - added
#[[TaskSliderFrame]] - added
#[[TaskTemplate]] - added
#[[TaskViewTemplate]] - added
#[[Test contact]] - added
#[[Test contact group]] - added
#[[Test goal]] - added
#[[Test project]] - added
#[[Test task]] - added
#[[The TiddlyDu3 layout]] - added
#[[This week's appointments]] - added
#[[TiddlersBarPluginMG]] - added
#[[TiddlyWiki Central at giffmex.org]] - added
#[[ToggleLeftSidebar]] - added
#[[ToggleRightSidebar]] - added
#[[ToggleTagPlugin]] - added
#[[ToolbarCommands]] - added
#[[TopMenu]] - added
#[[TopMenuStyle]] - added
#[[TopMenuX2]] - added
#[[TwHelpSearchPlugin]] - added
#[[Urgent]] - added
#[[ViewTemplate]] - added
#[[Visit, meet with]] - added
#[[Waiting]] - added
#[[Welcome]] - added
#[[What is GTD?]] - added
#[[Write]] - added
#[[zzConfigOptions]] - added
<<<
Use this inbox in addition to your e-mail inbox and physical inbox to gather unprocessed to-do items. You will process your next actions from your inboxes.
!Unprocessed items
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|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
<<<
2008.03.03 [1.9.2] corrected declaration of wikifyPlainText() for 'TW 2.1.x compatibility fallback' (fixes Safari "parse error")
2008.02.23 [1.9.1] in onclick function, use string instead of array for 'bufferedHTML' attribute on link element (fixes IE errors)
2008.02.21 [1.9.0] 'onclick' scripts now allow returned text (or document.write() calls) to be wikified into a span that immediately follows the onclick link. 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.
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.inlineJavascript= {major: 1, minor: 9, revision: 2, date: new Date(2008,3,3)};
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) { // load a script library
// make script tag, set src, add to body to execute, then remove for cleanup
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // there is script code
if (show) // show inline script code in tiddler output
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create a link to an 'onclick' script
// add a link, define click handler, save code in link (pass 'place'), set link attributes
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){"+fixup+"\n};_out(this);"
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 inline script code
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var code="function _out(place){"+fixup+"\n};_out(w.output);"
try { var out=eval(code); } 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();
}
//}}}
<<forEachTiddler where 'tiddler.tags.contains("Investigate, order")' sortBy 'tiddler.title'>>
<<siteMap [[Learn to Fly]] . sliders>>
/***
|''Name:''|LegacyStrikeThroughPlugin|
|''Description:''|Support for legacy (pre 2.1) strike through formatting|
|''Version:''|1.0.2|
|''Date:''|Jul 21, 2006|
|''Source:''|http://www.tiddlywiki.com/#LegacyStrikeThroughPlugin|
|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''License:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.0|
***/
//{{{
// Ensure that the LegacyStrikeThrough Plugin is only installed once.
if(!version.extensions.LegacyStrikeThroughPlugin) {
version.extensions.LegacyStrikeThroughPlugin = {installed:true};
config.formatters.push(
{
name: "legacyStrikeByChar",
match: "==",
termRegExp: /(==)/mg,
element: "strike",
handler: config.formatterHelpers.createElementAndWikify
});
} //# end of "install only once"
//}}}
/***
|''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);
}
//}}}
<<siteMap [[MGComments09Feb]] . sliders>>
There's couple of things you might have a look at Dave.
If you close Welcome there's no way back to it except search or reload
as it's tagged excludeLists. I think you should do what I do and put
a "Home" button on it or at least have a way to get to a default page.
On "Test goal" the toolbar shows "new tiddler" in two places. I've
perused the GoalViewTemplate but I can't figure out what you intended.
Also your NoteNote is missing.
Also you have left off the tag chooser from the EditTemplate which is
a bit disconcerting.
Since you said it was essentially finished and uploaded I've
customized it extensively (as I do:-) and started using it to give it
a proper test. So if you could document your further changes
incrementally as change notices rather than just dumping them into a
new completed version I'd appreciate it (others who have started to
load it up may welcome this approach as well as it is rather
complicated).
<<siteMap [[MGComments10Feb]] . sliders>>
Hi Dave it's looking pretty good, you have put in a lot of work and thought into it. Congratulations it has to be the best personal organizer yet.
I wonder if you have given any thought to how to clean it up when finishing projects, tasks and goals.
Could be possible to search for tags and delete all tags say "Test Goal" and clean out the whole lot of tiddlers associated leaving no orphan tiddlers?
One problem with that idea at present is that you allow 'new projects' to be created under Goals. So while the new project will show up under Projects OK it is at risk of being deleted as it is also tagged with goal.
Perhaps this facility should be disallowed. I have removed 'make a new project' from my GoalViewTemplate.
It's still early days and I haven't explored how many interrelationships that could be created to prevent deletion by tag without something important disappearing or leaving orphans.
By the way your Acknowledgements & license still has NoBrainerNotes in it.
Also I have reconfigured the tabs so that Help isn't hidden behind the by Extra tab by swapping the two around. I didn't rename any tiddlers just the labels in the tabs.
You may be interested in seeing it I've added my usual tweaks etc. to it. I integrated TWT-Notes/NoBrainerNotes into it also, mostly to see if I could do it but it could prove useful.
It's at http://twtudu.tiddlyspot.com/
Morris
Thanks Dave mine's fixed.
Something even more important is the sub menus in the tabs for
creating new goals, tasks contacts etc. on Tiddlydu3 seems to be
missing on the latest version.
I'll discuss the philosophy re: goals and projects later when I have
time :-) In His infinite wisdom we were all made different for a
reason - trouble is it's up to us to find out why:-)
Morris
<<formTiddler NewContactTemplate>><data>{"firstname":"Morris","lastname":"Gray"}</data>
<<tiddler UTC>>{{textcenter{@@color:#006;Personal Organizer@@}}}<<tabs txtMenuMenu
"Tasks" "Tasks" TabToDo
"Calendars" "Calendars" TabCalendars
"Contacts" "Contacts" TabContactsTab
"Info" "Info" TabInfo
"Help" "Extras" TabExtras>>
{{textcenter{@@color:#006;My Notes@@}}}<<tabs "" "TiddlyDu3" "TiddlyDu3" "TiddlyDu3" "MyTopic" "MyTopic" "MyTopic">>
@@padding-left:1em;[[Acknowledgements & license]]@@
<!-- Start of StatCounter Code -->
<script type="text/javascript">
var sc_project=4462955;
var sc_invisible=1;
var sc_partition=55;
var sc_click_stat=1;
var sc_security="3fe8a30b";
</script>
<script type="text/javascript" src="http://www.statcounter.com/counter/counter.js"></script><noscript><div class="statcounter"></div></noscript>
<!-- End of StatCounter Code -->
/***
| Name:|''monkeyTagger''|
| Created by:|SaqImtiaz|
| Location:|http://tw.lewcid.org/|
| Version:|0.9 (08-Apr-2006)|
| Requires:|~TW2.07|
[Snip - see plugin documentation at the link above]
!CODE
***/
//{{{
config.macros.monkeyTagger= {};
//config.macros.monkeyTagger.dropdownchar = (document.all?"▼":"▾"); // the fat one is the only one that works in IE
config.macros.monkeyTagger.dropdownchar = "▼"; // uncomment previous line and comment this for smaller version in FF
config.macros.monkeyTagger.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var nAV = paramString.parseParams('test', null, true);
if ((nAV[0].arrow)&&(nAV[0].arrow[0])=='false')
var arrow=': ';
else
var arrow=': '+ config.macros.monkeyTagger.dropdownchar;
if((nAV[0].source)&&(nAV[0].source[0])!='.')
{var tagToTrack = nAV[0].source[0]}
else if(params[0]&&(params[0]!='.'))
{var tagToTrack = params[0]}
else
{return false;};
var monkeylabel = ((nAV[0].label)&&(nAV[0].label[0])!='.')?nAV[0].label[0]+arrow: tagToTrack+arrow;
var logmode = ((nAV[0].logging)&&(nAV[0].logging[0])!='.')?nAV[0].logging[0]: "false";
if ((nAV[0].anchor)&&(nAV[0].anchor[0])!='.')
var anchor = nAV[0].anchor[0];
var monkeytooltip=tagToTrack + ' :';
if(tiddler instanceof Tiddler)
{var title = tiddler.title;
var addcomment = function(tiddler,newTag){
var now = new Date();
var timeFormat= 'DD/0MM/YY 0hh:0mm';
var formattednow= now.formatString(timeFormat);
var txt="\n*''"+tagToTrack+"'' set as ''"+newTag+"'' on "+formattednow;
if (anchor && anchor!='.')
{var pos=tiddler.text.indexOf(anchor);
if (pos!=-1) {pos=pos + anchor.length}
else if (pos==-1) {pos=tiddler.text.length}}
else if (!anchor){var pos = tiddler.text.length;};
tiddler.set(null,tiddler.text.substr(0,pos)+txt+tiddler.text.substr(pos));
story.refreshTiddler(tiddler.title,null,true);
return false;
}
var ontagclick = function(e) {
if (!e) var e = window.event;
var tag = this.getAttribute("tag");
var t=store.getTiddler(title);
if (!t || !t.tags) return;
if (t.tags.find(tag)==null)
{t.tags.push(tag)
if (logmode=="true"){addcomment(t,tag);}}
else
{t.tags.splice(t.tags.find(tag),1)};
story.saveTiddler(title);
story.refreshTiddler(title,null,true);
return false;
};
var onclick = function(e) {
if (!e) var e = window.event;
var popup = Popup.create(this);
var thistiddler=store.getTiddler(title);
var taggedarray = new Array();
var tagslabel = new Array();
var taggedtiddlers = store.getTaggedTiddlers(tagToTrack);
for (var t=0; t<taggedtiddlers.length; t++){
var taggedtitle= ((taggedtiddlers[t]).title);
taggedarray.push(taggedtitle);}
for (var t=0; t<taggedarray.length; t++){
var temptag = taggedarray[t];
if (thistiddler.tags.find(temptag)==null)
{var temptag='[ ] '+ temptag;
tagslabel.push(temptag);}
else
{var temptag ='[x] '+ temptag;
tagslabel.push(temptag);}
}
if(tagslabel.length == 0)
createTiddlyText(createTiddlyElement(popup,"li"),('no '+tagToTrack));
for (var t=0; t<tagslabel.length; t++)
{
var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tagslabel[t],("toggle '"+ ([taggedarray[t]]))+"'",ontagclick);
theTag.setAttribute("tag",taggedarray[t]);
}
Popup.show(popup,false);
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
};
//createTiddlyButton(place,monkeylabel,monkeylabel,onclick);
var createdropperButton = function(place){
var sp = createTiddlyElement(place,"span",null,"monkeytaggerbutton");
var theDropDownBtn = createTiddlyButton(sp,monkeylabel,monkeytooltip,onclick);
};
createdropperButton(place);
}
};
setStylesheet(
".toolbar .monkeytaggerbutton {margin-right:0em; border:0px solid #fff; padding:0px; padding-right:0px; padding-left:0px;}\n"+
".monkeytaggerbutton a.button {padding:2px; padding-left:2px; padding-right:2px;}\n"+
// ".monkeytaggerbutton {font-size:130%;}\n"+
//".monkeytaggerbutton .button {color:#703;}\n"+
"",
"MonkeyTaggerStyles");
//}}}
You shouldn't need to know much about ~TiddlyWiki to operate ~TiddlyDu3, but in case you do, here are five helpful sources of information for you:
#We have an [[introductory slideshow|http://www.slideshare.net/guest102a23/an-introduction-to-tiddlywiki-revised?src=embed]] about ~TiddlyWiki on Slideshare (it features the previous version, ~TiddlyDu2, but is still a helpful overview).
#We have a beginner's-level ~TiddlyWiki tutorial called [[TiddlyWiki for the rest of us|http://www.giffmex.org/twfortherestofus.html]].
#The [[Google Group|http://groups-beta.google.com/group/TiddlyWiki]] devoted to ~TiddlyWiki has a host of experts standing by to help you out when you're stuck.
#For a more complete tutorial, see Morris Gray's [[TW Help|http://tiddlyspot.com/twhelp/]]
#The in-process official [[documentation site|http://www.tiddlywiki.org/wiki]]
<<siteMap [[Morris]] . sliders>>
<<siteMap [[MorrisBusiness]] . sliders>>
<<siteMap [[MorrisContacts]] . sliders>>
'My Info' is merely a handy index for information you'd like to keep on hand at all times - bank pins, Internet passwords, special instructions, driving directions, etc. Just click 'New piece of info' to create a new note with important info. Click 'done', and your info will be added to the 'My info' tab to the left when you refresh.
{{bluey{MyTopic}}}@@padding-left:0.5em;font-size:7pt;<<newTiddler title: 'Enter the name for your new sub-topic here' tag: 'MyTopic' 'Atopic' label: 'subTopic | ' text: {{store.getTiddlerText("SliderFrame")}} label: 'New Master Topic'>><script label="refresh">
story.forEachTiddler(function(t,e)
{story.refreshTiddler(t,null,true)});
refreshDisplay();
return false;
</script>@@
<<forEachTiddler
where
'tiddler.tags.contains("MyTopic")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|Author|Eric Shulman - ELS Design Studios with one tweak by Dave Gifford. MAY BE OUTDATED! FOR A CLEAN, UPDATED COPY, FOLLOW THE SOURCE LINK ABOVE|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!Configuration
<<<
<<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
>Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
>In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class). In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release. Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};
// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkFloatingSlidersAnimate===undefined)
config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE
// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");
// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
window.removeCookie=function(name) {
document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
}
}
config.formatters.push( {
name: "nestedSliders",
match: "\\n?\\+{3}",
terminator: "\\s*\\={3}\\n?",
lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\>]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\>)?(\\.\\.\\.)?\\s*",
handler: function(w)
{
lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
{
var defopen=lookaheadMatch[1];
var cookiename=lookaheadMatch[2];
var header=lookaheadMatch[3];
var panelwidth=lookaheadMatch[4];
var transient=lookaheadMatch[5];
var hover=lookaheadMatch[6];
var buttonClass=lookaheadMatch[7];
var label=lookaheadMatch[8];
var openlabel=lookaheadMatch[9];
var panelID=lookaheadMatch[10];
var blockquote=lookaheadMatch[11];
var deferred=lookaheadMatch[12];
// location for rendering button and panel
var place=w.output;
// default to closed, no cookie, no accesskey, no alternate text/tip
var show="none"; var cookie=""; var key="";
var closedtext=" ►"; var closedtip="";
var openedtext=" ►"; var openedtip="";
// extra "+", default to open
if (defopen) show="block";
// cookie, use saved open/closed state
if (cookiename) {
cookie=cookiename.trim().slice(1,-1);
cookie="chkSlider"+cookie;
if (config.options[cookie]==undefined)
{ config.options[cookie] = (show=="block") }
show=config.options[cookie]?"block":"none";
}
// parse label/tooltip/accesskey: [label=X|tooltip]
if (label) {
var parts=label.trim().slice(1,-1).split("|");
closedtext=parts.shift();
if (closedtext.substr(closedtext.length-2,1)=="=")
{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
openedtext=closedtext;
if (parts.length) closedtip=openedtip=parts.join("|");
else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
}
// parse alternate label/tooltip: [label|tooltip]
if (openlabel) {
var parts=openlabel.trim().slice(1,-1).split("|");
openedtext=parts.shift();
if (parts.length) openedtip=parts.join("|");
else openedtip="hide "+openedtext;
}
var title=show=='block'?openedtext:closedtext;
var tooltip=show=='block'?openedtip:closedtip;
// create the button
if (header) { // use "Hn" header format instead of button/link
var lvl=(header.length>5)?5:header.length;
var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,buttonClass,title);
btn.onclick=onClickNestedSlider;
btn.setAttribute("href","javascript:;");
btn.setAttribute("title",tooltip);
}
else
var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
btn.innerHTML=title; // enables use of HTML entities in label
// set extra button attributes
btn.setAttribute("closedtext",closedtext);
btn.setAttribute("closedtip",closedtip);
btn.setAttribute("openedtext",openedtext);
btn.setAttribute("openedtip",openedtip);
btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
btn.defOpen=defopen!=null; // save default open/closed state (boolean)
btn.keyparam=key; // save the access key letter ("" if none)
if (key.length) {
btn.setAttribute("accessKey",key); // init access key
btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
}
btn.setAttribute("hover",hover?"true":"false");
btn.onmouseover=function(ev) {
// optional 'open on hover' handling
if (this.getAttribute("hover")=="true" && this.sliderPanel.style.display=='none') {
document.onclick.call(document,ev); // close transients
onClickNestedSlider(ev); // open this slider
}
// mouseover on button aligns floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
}
// create slider panel
var panelClass=panelwidth?"floatingPanel":"sliderPanel";
if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
panel.button = btn; // so the slider panel know which button it belongs to
btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
panel.defaultPanelWidth=(panelwidth && panelwidth.length>2)?panelwidth.slice(1,-1):"";
panel.setAttribute("transient",transient=="*"?"true":"false");
panel.style.display = show;
panel.style.width=panel.defaultPanelWidth;
panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }
// render slider (or defer until shown)
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
if ((show=="block")||!deferred) {
// render now if panel is supposed to be shown or NOT deferred rendering
w.subWikify(blockquote?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
// align floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
}
else {
var src = w.source.substr(w.nextMatch);
var endpos=findMatchingDelimiter(src,"+++","===");
panel.setAttribute("raw",src.substr(0,endpos));
panel.setAttribute("blockquote",blockquote?"true":"false");
panel.setAttribute("rendered","false");
w.nextMatch += endpos+3;
if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
}
}
}
}
)
function findMatchingDelimiter(src,starttext,endtext) {
var startpos = 0;
var endpos = src.indexOf(endtext);
// check for nested delimiters
while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
// count number of nested 'starts'
var startcount=0;
var temp = src.substring(startpos,endpos-1);
var pos=temp.indexOf(starttext);
while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
// set up to check for additional 'starts' after adjusting endpos
startpos=endpos+endtext.length;
// find endpos for corresponding number of matching 'ends'
while (startcount && endpos!=-1) {
endpos = src.indexOf(endtext,endpos+endtext.length);
startcount--;
}
}
return (endpos==-1)?src.length:endpos;
}
//}}}
//{{{
window.onClickNestedSlider=function(e)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
while (theTarget && theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
if (!theTarget) return false;
var theSlider = theTarget.sliderPanel;
var isOpen = theSlider.style.display!="none";
// if SHIFT-CLICK, dock panel first (see [[MoveablePanelPlugin]])
if (e.shiftKey && config.macros.moveablePanel) config.macros.moveablePanel.dock(theSlider,e);
// toggle label
theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
// toggle tooltip
theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));
// deferred rendering (if needed)
if (theSlider.getAttribute("rendered")=="false") {
var place=theSlider;
if (theSlider.getAttribute("blockquote")=="true")
place=createTiddlyElement(place,"blockquote");
wikify(theSlider.getAttribute("raw"),place);
theSlider.setAttribute("rendered","true");
}
// show/hide the slider
if(config.options.chkAnimate && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
else
theSlider.style.display = isOpen ? "none" : "block";
// reset to default width (might have been changed via plugin code)
theSlider.style.width=theSlider.defaultPanelWidth;
// align floater panel position with target button
if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);
// if showing panel, set focus to first 'focus-able' element in panel
if (theSlider.style.display!="none") {
var ctrls=theSlider.getElementsByTagName("*");
for (var c=0; c<ctrls.length; c++) {
var t=ctrls[c].tagName.toLowerCase();
if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
{ try{ ctrls[c].focus(); } catch(err){;} break; }
}
}
var cookie=theTarget.sliderCookie;
if (cookie && cookie.length) {
config.options[cookie]=!isOpen;
if (config.options[cookie]!=theTarget.defOpen) window.saveOptionCookie(cookie);
else window.removeCookie(cookie); // remove cookie if slider is in default display state
}
// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
// prevent clicks *within* a slider button from being processed by browser
// but allow plain click to bubble up to page background (to close transients, if any)
if (e.shiftKey || theTarget!=resolveTarget(e))
{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
Popup.remove(); // close open popup (if any)
return false;
}
//}}}
//{{{
// click in document background closes transient panels
document.nestedSliders_savedOnClick=document.onclick;
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);
if (document.nestedSliders_savedOnClick)
var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
// if click was inside a popup... leave transient panels alone
var p=target; while (p) if (hasClass(p,"popup")) break; else p=p.parentNode;
if (p) return retval;
// if click was inside transient panel (or something contained by a transient panel), leave it alone
var p=target; while (p) {
if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
p=p.parentNode;
}
if (p) return retval;
// otherwise, find and close all transient panels...
var all=document.all?document.all:document.getElementsByTagName("DIV");
for (var i=0; i<all.length; i++) {
// if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
// otherwise, if the panel is currently visible, close it by clicking it's button
if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button})
if (!hasClass(all[i],"floatingPanel")&&!hasClass(all[i],"sliderPanel")) all[i].style.display="none";
}
return retval;
};
//}}}
//{{{
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
if (hasClass(panel,"floatingPanel") && !hasClass(panel,"undocked")) {
// see [[MoveablePanelPlugin]] for use of 'undocked'
var rightEdge=document.body.offsetWidth-1;
var panelWidth=panel.offsetWidth;
var left=0;
var top=btn.offsetHeight;
if (place.style.position=="relative" && findPosX(btn)+panelWidth>rightEdge) {
left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
if (findPosX(btn)+left<0) left=-findPosX(btn); // stay within left edge
}
if (place.style.position!="relative") {
var left=findPosX(btn);
var top=findPosY(btn)+btn.offsetHeight;
var p=place; while (p && !hasClass(p,'floatingPanel')) p=p.parentNode;
if (p) { left-=findPosX(p); top-=findPosY(p); }
if (left+panelWidth>rightEdge) left=rightEdge-panelWidth;
if (left<0) left=0;
}
panel.style.left=left+"px"; panel.style.top=top+"px";
}
}
//}}}
//{{{
// TW2.1 and earlier:
// hijack Slider stop handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }
// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
Morpher.prototype.coreStop = Morpher.prototype.stop;
Morpher.prototype.stop = function() {
this.coreStop.apply(this,arguments);
var e=this.element;
if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
// adjust panel overflow and position after animation
e.style.overflow = "visible";
if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
}
};
}
//}}}
Type the text for 'New piece of info'
<html><span style="padding-right:0.15em;" macro='monkeyTagger contactgroup'></span></html>
<html>
<style>
.rolodex table {
border: 0px solid;
}
.rolodex tr, .rolodex td {
border: 0px solid;
}
</style>
<span class="rolodex">
<table>
<tr>
<td align="right"><b>Firstname:</b></td>
<td colspan="3"><input name=firstname type=text style="width:100%" /></td></tr>
<tr>
<td align="right"><b>Lastname:</b></td>
<td colspan="3"><input name=lastname type=text style="width:100%" /></td></tr>
<tr>
<td align="right"><b>Email:</b></td>
<td colspan="3"><input name=email type=text style="width:100%" /></td></tr>
<tr>
<td align="right"><b>Phone:</b></td>
<td colspan="3"><input name=phone type=text style="width:100%" /></td></tr>
<tr>
<td align="right" valign="top"><b>Address:</b></td>
<td colspan="3"><textarea name=address rows="2" cols="40" style="width:100%" ></textarea></td></tr>
<tr>
<td align="right"><b>City:</b></td>
<td colspan="3"><input name=city type=text style="width:100%" /></td></tr>
<tr>
<td align="right"><b>State/Province:</b></td>
<td><input name=state type=text size="5" /></td>
<td align="right"><b style="width:100%" >ZIP/Postal Code:</b></td>
<td><input name=zip type=text size="5" style="width:100%" /></td></tr>
<tr>
<td align="right"><b>Country:</b></td>
<td colspan="3"><input name=country type=text style="width:100%" /></td></tr>
<tr>
<td align="right"><b>Webpage:</b></td>
<td colspan="3"><input name=webpage type=text style="width:100%" /></td>
<tr>
<td align="right"><b>Birthday:</b></td>
<td colspan="3"><input name=birthday type=text style="width:100%" /></td></tr></span></html>
! Notes
/***
|Name:|NewHerePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
newHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
},
newJournalHere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
}
});
//}}}
{{bluey{MYNEWMASTERTOPIC}}}@@padding-left:0.5em;font-size:7pt;<<newTiddler title: 'Enter the name for your new sub topic here' tag: 'MYNEWMASTERTOPIC' 'Atopic' label: 'subTopic | ' text: {{store.getTiddlerText("SliderFrame")}} label: 'New Master Topic'>><script label="refresh">
story.forEachTiddler(function(t,e)
{story.refreshTiddler(t,null,true)});
refreshDisplay();
return false;
</script>@@
<<forEachTiddler
where
'tiddler.tags.contains("MYNEWMASTERTOPIC")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
/***
|Name:|NewTherePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>, modified by giffmex|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
newThere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]] tag:Atopic>>",place,null,tiddler);
}
},
newJournalThere: {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
}
}
});
//}}}
/***
|Name|OpenTaggedTiddlersMacro|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#OpenTaggedTiddlersMacro]]|
|Version|0.1.2|
|Author|[[one_each|http://groups.google.com/group/TiddlyWiki/browse_thread/t/77d70c4e01e7c6fa]]|
|Contributor|FND|
|License|public domain|
|~CoreVersion|1.2|
|Type|macro|
|Requires|N/A|
|Overrides|N/A|
|Description|open all tiddlers with a given tag|
!Usage
{{{
<<openAll [[tag]] ["title:..."] [closeAllFirst]>>
}}}
!Options
Although the tag is required as the first parameter, the options listed below are optional and may appear in any order.
|!Option|!Description|
|closeAllFirst|close all other tiddlers first|
|<nowiki>title:Title</nowiki>|button caption (enclose in quotation marks if the text contains spaces)|
!Examples
|!Code|!Output|
|{{{<<openAll systemConfig>>}}}|<<openAll systemConfig>>|
|{{{<<openAll systemConfig closeAllFirst>>}}}|<<openAll systemConfig closeAllFirst>>|
|{{{<<openAll systemConfig "title:Open system tiddlers">>}}}|<<openAll systemConfig "title:Open system tiddlers">>|
!Revision History
!!v0.1.1 (2005-09-01)
* initial release [[by one_each|http://groups.google.com/group/TiddlyWiki/browse_thread/t/77d70c4e01e7c6fa]] (named "openAll macro")
!!v0.1.2 (2005-06-30)
* minor code cleanup by FND
* removed {{{reverseOrder}}} parameter due to incompatibility with TiddlyWiki 2.2
* renamed to OpenTaggedTiddlersMacro
!Issues / To Do
* code cleanup / refactoring
!Code
***/
//{{{
version.extensions.openAll = {major: 0, minor: 1, revision: 1, date: new Date("Jun 30, 2007")};
config.macros.openAll = {}
config.macros.openAll.handler = function(place,macroName,params) {
var title = "Open all " + params[0];
var closeAllFirst = "false";
for(var i = 1; i < params.length; i++) { // skip the first parameter
if(params[i] == "closeAllFirst")
closeAllFirst = "true";
if(params[i].substring(0,6) == "title:")
title = params[i].substring(6);
}
var btn = createTiddlyButton(place,title,null,onClickOpenAllMacro);
btn.setAttribute("tag",params[0]);
btn.setAttribute("closeAllFirst",closeAllFirst);
}
// Event handler for 'openAll' macro
function onClickOpenAllMacro(e)
{
if (!e) var e = window.event;
var tag = this.getAttribute("tag");
var tagged = store.getTaggedTiddlers(tag);
if(this.getAttribute("closeAllFirst") == "true")
story.closeAllTiddlers();
for(var t=tagged.length-1; t>=0; t--)
displayTiddler(this,tagged[t].title,0,null,null,false,e.shiftKey || e.altKey);
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
<<tiddler TspotOptions>>These InterfaceOptions for customising TiddlyWiki are saved in your browser
Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)
<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations
----
Also see AdvancedOptions
<!--{{{-->
<div class='header' macro='gradient vert #00c #003'>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='topMenu'><span class='topMenu' refresh='content' tiddler='TopMenu'></span></div>
</div>
<div id='topMenu2'><span class='topMenu2' refresh='content' tiddler='TopMenu2'></span></div>
</div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' force='true' 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"
});
*/
//}}}
<<formTiddler NewContactTemplate>><data>{"firstname":"Patricia"}</data>
<<forEachTiddler where 'tiddler.tags.contains("Phone calls")' sortBy 'tiddler.title'>>
<<forEachTiddler where 'tiddler.tags.contains("Plan, organize")' sortBy 'tiddler.title'>>
<script label="PluginIdent" title="create a list of all installed plugins">
var plugins=window.store.getTaggedTiddlers('systemConfig','title');
var out='|>|>|>|>|>|bgcolor:#9ae;!Plugin Information from Headers|h\n';
out+='|bgcolor:#abf;!Plugin|bgcolor:#abf;!Modified|bgcolor:#abf;!Size|bgcolor:#abf;!Author|bgcolor:#abf;!Version|bgcolor:#abf;!CoreVersion|h\n|sortable|k\n';
out+=plugins.map(function(t) {
return '|'+'[['+t.title+']]'
+'|'+t.modified.formatString('YYYY.0MM.0DD')
+'| '+t.text.length
+'|'+store.getTiddlerSlice(t.title,'Author')
+'|'+store.getTiddlerSlice(t.title,'Version')
+'|'+store.getTiddlerSlice(t.title,'CoreVersion')+'|';
}).join('\n');
config.shadowTiddlers.PluginIdent=out;
story.displayTiddler(null,'PluginIdent');
</script>
<<forEachTiddler
where 'tiddler.tags.contains("systemConfig")'
sortBy 'tiddler.title.toLowerCase()'
write '"|[[" + tiddler.title +"]]" + "|[["+tiddler.text.length+"]]" + "|[[" +tiddler.modified.formatString("YYYY.0MM.0DD") + "]]|"
+ store.getTiddlerSlice(tiddler.title, "Author") + "|"
+ store.getTiddlerSlice(tiddler.title, "Version") + "|"
+ store.getTiddlerSlice(tiddler.title, "CoreVersion")+"|\n"'
begin '"|sortable|k\n"
+"|>|>|>|>|>|!Information from Plugin Headers (script by M. Gray)|h\n"
+ "|!Plugin (sortable)|!Size|!Modified|!Author|!Version|!CoreVersion|h\n"'
>>
<<siteMap [[Enter the name for your new project here, too]] . sliders>>
|bgcolor(#eeeeee):@@white-space: nowrap;<html><span style="padding-right:0.15em;" macro='monkeyTagger goal'></span> </html>@@|Select the life goal this project most closely relates to.|
|bgcolor(#eeeeee):@@white-space: nowrap;<html><span style="padding-right:0.15em;" macro='monkeyTagger status'></span> </html>@@|Select any and all statuses that apply. Delete the project if it is done and no reporting is needed.|
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span style="padding-right:0em;" macro='tagger'></span><span class='newbutton' style='padding-right: 0.5em;' macro='newHere title:"Enter the name for your new task here" label:"*New task for this project*" tag:"task" text:{{store.getTiddlerText("TaskSliderFrame")}}'></span></div>
<div class='title' macro='view title'></div>
<span macro='formTiddler ProjectTemplate'></span>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
|Name:|QuickOpenTagPlugin|
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
config.quickOpenTag = {
dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?
createTagButton: function(place,tag,excludeTiddler) {
// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
var splitTag = tag.split("|");
var pretty = tag;
if (splitTag.length == 2) {
tag = splitTag[1];
pretty = splitTag[0];
}
var sp = createTiddlyElement(place,"span",null,"quickopentag");
createTiddlyText(createTiddlyLink(sp,tag,false),pretty);
var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tag]),onClickTag);
theTag.setAttribute("tag",tag);
if (excludeTiddler)
theTag.setAttribute("tiddler",excludeTiddler);
return(theTag);
},
miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tagged = store.getTaggedTiddlers(tiddler.title);
if (tagged.length > 0) {
var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
theTag.setAttribute("tag",tiddler.title);
theTag.className = "miniTag";
}
},
allTagsHandler: function(place,macroName,params) {
var tags = store.getTags(params[0]);
var filter = params[1]; // new feature
var ul = createTiddlyElement(place,"ul");
if(tags.length == 0)
createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
for(var t=0; t<tags.length; t++) {
var title = tags[t][0];
if (!filter || (title.match(new RegExp('^'+filter)))) {
var info = getTiddlyLinkInfo(title);
var theListItem =createTiddlyElement(ul,"li");
var theLink = createTiddlyLink(theListItem,tags[t][0],true);
var theCount = " (" + tags[t][1] + ")";
theLink.appendChild(document.createTextNode(theCount));
var theDropDownBtn = createTiddlyButton(theListItem," " +
config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);
theDropDownBtn.setAttribute("tag",tags[t][0]);
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
" { margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
" { border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
" { margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
" { margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
" /* looks better in right justified main menus */",
" { margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }",
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",
"/*}}}*/",
""].join("\n"),
init: function() {
// we fully replace these builtins. can't hijack them easily
window.createTagButton = this.createTagButton;
config.macros.allTags.handler = this.allTagsHandler;
config.macros.miniTag = { handler: this.miniTagHandler };
config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;
store.addNotification("QuickOpenTagStyles",refreshStyles);
}
}
config.quickOpenTag.init();
//}}}
<<forEachTiddler where 'tiddler.tags.contains("Read")' sortBy 'tiddler.title'>>
@@font-size:10pt;<script label="refresh content">
story.forEachTiddler(function(t,e)
{story.refreshTiddler(t,null,true)});
refreshDisplay();
return false;
</script>@@
/***
***/
//{{{
config.commands.refresh = {
text: 'refresh',
tooltip: 'Refresh this tiddler',
handler: function(e,src,title) {
clearMessage();
story.refreshTiddler(title,false,true); // force=true
return false;
}
};
//}}}
/***
|''Name:''|RefreshTiddlerPlugin|
|''Description:''|Refresh an entire tiddler with optional periodic re-refresh|
|''Date:''|Oct 3, 2006|
|''Source:''|http://solo.dc3.com/tw/index.html#RefreshTiddlerPlugin|
|''Author:''|Bob Denny ~DC-3 Dreams, SP|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''Version:''|1.0.4|
|''~CoreVersion:''|2.0.11, 2.1.0|
|''Browser:''|Firefox 1.5; Internet Explorer 6.0; Safari|
|''Require:''|CheckboxPlugin (http://www.TiddlyTools.com/#CheckboxPlugin)|
This macro provides a tiddler with refresh control. Why would you want this? Perhaps for a webcam feed which is updated every 15, 30, 60 secs etc... or RSS feed from an active news site etc.
At a minimum, a refresh button appears at the location of the macro invocation. Clicking this button causes the contents of the tiddler to be refreshed. Optionally, a checkbox may also be displayed with which the user can enable and disable automatic periodic refresh of the tiddler at a specified interval.
There are three optional parameters
|!Parameter|!Description|
|''1''|Button label, default "Refresh"|
|''2''|Button tooltip, default "Refresh this tiddler"|
|''3''|Periodic refresh interval, sec., default 0 (no periodic refresh checkbox)|
!!Revision History
<<<
''2006.09.13 [1.0.1]'' Initial creation, several days
''2006.09.22 [1.0.2]'' Make periodic refresh checkbox optional
''2006.09.29 [1.0.3]'' Refresh checkbox cookie names different from RefreshIframe.
''2006.10.03 [1.0.4]'' Lint check, validate on TW 2.1.0.
<<<
!!Code
***/
//{{{
version.extensions.RefreshTiddler = {
major: 1, minor: 0, revision: 4,
date: new Date(2006, 10, 3),
type: 'macro',
source: "#RefreshTiddlerPlugin"
};
config.macros.RefreshTiddler =
{
states: { }, // Associative array of refresh states indexed by tiddler name
handler: function(place, macroName, params, wikifier, paramString, tiddler)
{
var tidTitle = tiddler.title; // Shortcut
if(!this.states[tidTitle]) this.states[tidTitle] = { // Array of state objects for refreshed tiddlers
butLabel: "",
butTooltip: "",
refInterval: 0,
doRefresh: false,
initPerRef: false,
timerId: 0,
chkBox: null
};
var state = this.states[tidTitle]; // Shortcut
state.butLabel = params[0] ? params[0] : "Refresh this list"; // Make these react to edits
state.butTooltip = params[1] ? params[1] : "Refresh this tiddler";
state.refInterval = params[2] ? params[2] : 0; // 0 = no periodic refresh checkbox
var btn = createTiddlyButton(place, state.butLabel, state.butTooltip, this.onButClick);
btn.name = tidTitle; // Set button name to tiddler name (see onButClick())
if(state.refInterval > 0) // If periodic refresh wanted
{
wikify(" [ =chkPerRefTid" + tiddler.created.convertToYYYYMMDDHHMM() + // Uniquify chkbox ID
"{config.macros.RefreshTiddler.states[\"" + tidTitle + "\"].chkBox = this;}" +
"{config.macros.RefreshTiddler.onChkClick(\"" + tidTitle + "\");}] " +
state.butLabel + " every " + state.refInterval + " seconds", place);
state.timerId = 0;
if(!state.initPerRef) this.onChkClick(tidTitle); // Simulate checkbox click (state already from cookie)
}
},
onButClick: function(e)
{
if(!e) e = window.event;
var tidTitle = resolveTarget(e).name; // Name is the tiddler name!
//displayMessage("but " + tidTitle);
story.refreshTiddler(tidTitle, null, true);
return false;
},
onChkClick: function(tidTitle)
{
var state = this.states[tidTitle];
if(state.chkBox.checked) {
if(state.timerId) clearTimeout(state.timerId);
this.startRefresh(tidTitle);
} else {
state.doRefresh = false;
}
state.initPerRef = true;
},
startRefresh: function(tidTitle)
{
var state = this.states[tidTitle];
state.doRefresh = true;
//displayMessage("st " + tidTitle + " " + state.refInterval);
state.timerId = setTimeout("config.macros.RefreshTiddler.reRefresh(\"" +
tidTitle + "\")", state.refInterval * 1000);
},
reRefresh: function(tidTitle)
{
var state = this.states[tidTitle];
state.timerId = 0;
if(!state.doRefresh) return;
// Kill re-refresh cycle if tiddler closed or edited
var tidElem = document.getElementById(story.idPrefix + tidTitle); // DON'T GET CUTE! THIS IS CORRECT!
//**BUGBUG** Hardwired to EditTemplate!
if(!tidElem || tidElem.attributes['template'].value == "EditTemplate") // Prevent hidden or editing
{
state.initPerRef = false;
return;
}
//displayMessage("re " + tidTitle + " " + state.refInterval);
story.refreshTiddler(tidTitle, null, true);
state.timerId = setTimeout("config.macros.RefreshTiddler.reRefresh(\"" +
tidTitle + "\")", state.refInterval * 1000);
}
};
//}}}
/***
|''Name:''|ReminderPlugin|
|''Version:''|2.3.10 (Jun 28, 2007)|
|''Source:''|http://remindermacros.tiddlyspot.com|
|''Author:''|Jeremy Sheeley(pop1280 [at] excite [dot] com)<<br>>Maintainer: simon.baird@gmail.com|
|''Licence:''|[[BSD open source license]]|
|''Macros:''|reminder, showreminders, displayTiddlersWithReminders, newReminder|
|''TiddlyWiki:''|2.0+|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
This plugin provides macros for tagging a date with a reminder. Use the {{{reminder}}} macro to do this. The {{{showReminders}}} and {{{displayTiddlersWithReminder}}} macros automatically search through all available tiddlers looking for upcoming reminders.
!Installation
* Create a new tiddler in your tiddlywiki titled ReminderPlugin and give it the {{{systemConfig}}} tag. The tag is important because it tells TW that this is executable code.
* Double click this tiddler, and copy all the text from the tiddler's body.
* Paste the text into the body of the new tiddler in your TW.
* Save and reload your TW.
* You can copy some examples into your TW as well. See [[Simple examples]], [[Holidays]], [[showReminders]] and [[Personal Reminders]]
!Syntax:
|>|See [[ReminderSyntax]] and [[showRemindersSyntax]]|
!Revision history
* v2.3.10 (Jun 28, 2007)
** Removed window.story = window backwards compatibility hacks since they were breaking TW 2.2
* v2.3.9 (Apr 26, 2007)
** allow bracketed list format in tags param lets you use tags with spaces
* v2.3.8 (Mar 9, 2006)
**Bug fix: A global variable had snuck in, which was killing FF 1.5.0.1
**Feature: You can now use TIDDLER and TIDDLERNAME in a regular reminder format
* v2.3.6 (Mar 1, 2006)
**Bug fix: Reminders for today weren't being matched sometimes.
**Feature: Solidified integration with DatePlugin and CalendarPlugin
**Feature: Recurring reminders will now return multiple hits in showReminders and the calendar.
**Feature: Added TIDDLERNAME to the replacements for showReminders format, for plugins that need the title without brackets.
* v2.3.5 (Feb 8, 2006)
**Bug fix: Sped up reminders lots. Added a caching mechanism for reminders that have already been matched.
* v2.3.4 (Feb 7, 2006)
**Bug fix: Cleaned up code to hopefully prevent the Firefox 1.5.0.1 crash that was causing lots of plugins
to crash Firefox. Thanks to http://www.jslint.com
* v2.3.3 (Feb 2, 2006)
**Feature: newReminder now has drop down lists instead of text boxes.
**Bug fix: A trailing space in a title would trigger an infinite loop.
**Bug fix: using tag:"birthday !reminder" would filter differently than tag:"!reminder birthday"
* v2.3.2 (Jan 21, 2006)
**Feature: newReminder macro, which will let you easily add a reminder to a tiddler. Thanks to Eric Shulman (http://www.elsdesign.com) for the code to do this.
** Bug fix: offsetday was not working sometimes
** Bug fix: when upgrading to 2.0, I included a bit to exclude tiddlers tagged with excludeSearch. I've reverted back to searching through all tiddlers
* v2.3.1 (Jan 7, 2006)
**Feature: 2.0 compatibility
**Feature AlanH sent some code to make sure that showReminders prints a message if no reminders are found.
* v2.3.0 (Jan 3, 2006)
** Bug Fix: Using "Last Sunday (-0)" as a offsetdayofweek wasn't working.
** Bug Fix: Daylight Savings time broke offset based reminders (for example year:2005 month:8 day:23 recurdays:7 would match Monday instead of Tuesday during DST.
!Code
***/
//{{{
//============================================================================
//============================================================================
// ReminderPlugin
//============================================================================
//============================================================================
version.extensions.ReminderPlugin = {major: 2, minor: 3, revision: 8, date: new Date(2006,3,9), source: "http://remindermacros.tiddlyspot.com/"};
//============================================================================
// Configuration
// Modify this section to change the defaults for
// leadtime and display strings
//============================================================================
config.macros.reminders = {};
config.macros["reminder"] = {};
config.macros["newReminder"] = {};
config.macros["showReminders"] = {};
config.macros["displayTiddlersWithReminders"] = {};
config.macros.reminders["defaultLeadTime"] = [0,6000];
config.macros.reminders["defaultReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY";
config.macros.reminders["defaultShowReminderMessage"] = "DIFF: TITLE on DATE ANNIVERSARY -- TIDDLER";
config.macros.reminders["defaultAnniversaryMessage"] = "(DIFF)";
config.macros.reminders["untitledReminder"] = "Untitled Reminder";
config.macros.reminders["noReminderFound"] = "Couldn't find a match for TITLE in the next LEADTIMEUPPER days."
config.macros.reminders["todayString"] = "Today";
config.macros.reminders["tomorrowString"] = "Tomorrow";
config.macros.reminders["ndaysString"] = "DIFF days";
config.macros.reminders["emtpyShowRemindersString"] = "There are no upcoming events";
//============================================================================
// Code
// You should not need to edit anything
// below this. Make sure to edit this tiddler and copy
// the code from the text box, to make sure that
// tiddler rendering doesn't interfere with the copy
// and paste.
//============================================================================
//this object will hold the cache of reminders, so that we don't
//recompute the same reminder over again.
var reminderCache = {};
config.macros.showReminders.handler = function showReminders(place,macroName,params)
{
var now = new Date().getMidnight();
var paramHash = {};
var leadtime = [0,14];
paramHash = getParamsForReminder(params);
var bProvidedDate = (paramHash["year"] != null) ||
(paramHash["month"] != null) ||
(paramHash["day"] != null) ||
(paramHash["dayofweek"] != null);
if (paramHash["leadtime"] != null)
{
leadtime = paramHash["leadtime"];
if (bProvidedDate)
{
//If they've entered a day, we need to make
//sure to find it. We'll reset the
//leadtime a few lines down.
paramHash["leadtime"] = [-10000, 10000];
}
}
var matchedDate = now;
if (bProvidedDate)
{
var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);
var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);
matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound);
}
var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);
var elem = createTiddlyElement(place,"span",null,null, null);
var mess = "";
if (arr.length == 0)
{
mess += config.macros.reminders.emtpyShowRemindersString;
}
for (var j = 0; j < arr.length; j++)
{
if (paramHash["format"] != null)
{
arr[j]["params"]["format"] = paramHash["format"];
}
else
{
arr[j]["params"]["format"] = config.macros.reminders["defaultShowReminderMessage"];
}
mess += getReminderMessageForDisplay(arr[j]["diff"], arr[j]["params"], arr[j]["matchedDate"], arr[j]["tiddler"]);
mess += "\n";
}
wikify(mess, elem, null, null);
};
config.macros.displayTiddlersWithReminders.handler = function displayTiddlersWithReminders(place,macroName,params)
{
var now = new Date().getMidnight();
var paramHash = {};
var leadtime = [0,14];
paramHash = getParamsForReminder(params);
var bProvidedDate = (paramHash["year"] != null) ||
(paramHash["month"] != null) ||
(paramHash["day"] != null) ||
(paramHash["dayofweek"] != null);
if (paramHash["leadtime"] != null)
{
leadtime = paramHash["leadtime"];
if (bProvidedDate)
{
//If they've entered a day, we need to make
//sure to find it. We'll reset the leadtime
//a few lines down.
paramHash["leadtime"] = [-10000,10000];
}
}
var matchedDate = now;
if (bProvidedDate)
{
var leadTimeLowerBound = new Date().getMidnight().addDays(paramHash["leadtime"][0]);
var leadTimeUpperBound = new Date().getMidnight().addDays(paramHash["leadtime"][1]);
matchedDate = findDateForReminder(paramHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound);
}
var arr = findTiddlersWithReminders(matchedDate, leadtime, paramHash["tag"], paramHash["limit"]);
for (var j = 0; j < arr.length; j++)
{
displayTiddler(null, arr[j]["tiddler"], 0, null, false, false, false);
}
};
config.macros.reminder.handler = function reminder(place,macroName,params)
{
var dateHash = getParamsForReminder(params);
if (dateHash["hidden"] != null)
{
return;
}
var leadTime = dateHash["leadtime"];
if (leadTime == null)
{
leadTime = config.macros.reminders["defaultLeadTime"];
}
var leadTimeLowerBound = new Date().getMidnight().addDays(leadTime[0]);
var leadTimeUpperBound = new Date().getMidnight().addDays(leadTime[1]);
var matchedDate = findDateForReminder(dateHash, new Date().getMidnight(), leadTimeLowerBound, leadTimeUpperBound);
if (!store.getTiddler)
{
store.getTiddler=function(title) {return this.tiddlers[title];};
}
var title = window.story.findContainingTiddler(place).id.substr(7);
if (matchedDate != null)
{
var diff = matchedDate.getDifferenceInDays(new Date().getMidnight());
var elem = createTiddlyElement(place,"span",null,null, null);
var mess = getReminderMessageForDisplay(diff, dateHash, matchedDate, title);
wikify(mess, elem, null, null);
}
else
{
createTiddlyElement(place,"span",null,null, config.macros.reminders["noReminderFound"].replace("TITLE", dateHash["title"]).replace("LEADTIMEUPPER", leadTime[1]).replace("LEADTIMELOWER", leadTime[0]).replace("TIDDLERNAME", title).replace("TIDDLER", "[[" + title + "]]") );
}
};
config.macros.newReminder.handler = function newReminder(place,macroName,params)
{
var today=new Date().getMidnight();
var formstring = '<html><form>Year: <select name="year"><option value="">Every year</option>';
for (var i = 0; i < 5; i++)
{
formstring += '<option' + ((i == 0) ? ' selected' : '') + ' value="' + (today.getFullYear() +i) + '">' + (today.getFullYear() + i) + '</option>';
}
formstring += '</select> Month:<select name="month"><option value="">Every month</option>';
for (i = 0; i < 12; i++)
{
formstring += '<option' + ((i == today.getMonth()) ? ' selected' : '') + ' value="' + (i+1) + '">' + config.messages.dates.months[i] + '</option>';
}
formstring += '</select> Day:<select name="day"><option value="">Every day</option>';
for (i = 1; i < 32; i++)
{
formstring += '<option' + ((i == (today.getDate() )) ? ' selected' : '') + ' value="' + i + '">' + i + '</option>';
}
formstring += '</select> Reminder Title:<input type="text" size="40" name="title" value="please enter a title" onfocus="this.select();"><input type="button" value="ok" onclick="addReminderToTiddler(this.form)"></form></html>';
var panel = config.macros.slider.createSlider(place,null,"New Reminder","Open a form to add a new reminder to this tiddler");
wikify(formstring ,panel,null,store.getTiddler(params[1]));
};
// onclick: process input and insert reminder at 'marker'
window.addReminderToTiddler = function(form) {
if (!store.getTiddler)
{
store.getTiddler=function(title) {return this.tiddlers[title];};
}
var title = window.story.findContainingTiddler(form).id.substr(7);
var tiddler=store.getTiddler(title);
var txt='\n<<reminder ';
if (form.year.value != "")
txt += 'year:'+form.year.value + ' ';
if (form.month.value != "")
txt += 'month:'+form.month.value + ' ';
if (form.day.value != "")
txt += 'day:'+form.day.value + ' ';
txt += 'title:"'+form.title.value+'" ';
txt +='>>';
tiddler.set(null,tiddler.text + txt);
window.story.refreshTiddler(title,1,true);
store.setDirty(true);
};
function hasTag(tiddlerTags, tagFilters)
{
//Make sure we respond well to empty tiddlerTaglists or tagFilterlists
if (tagFilters.length==0 || tiddlerTags.length==0)
{
return true;
}
var bHasTag = false;
/*bNoPos says: "'till now there has been no check using a positive filter"
Imagine a filterlist consisting of 1 negative filter:
If the filter isn't matched, we want hasTag to be true.
Yet bHasTag is still false ('cause only positive filters cause bHasTag to change)
If no positive filters are present bNoPos is true, and no negative filters are matched so we have not returned false
Thus: hasTag returns true.
If at any time a positive filter is encountered, we want at least one of the tags to match it, so we turn bNoPos to false, which
means bHasTag must be true for hasTag to return true*/
var bNoPos=true;
for (var t3 = 0; t3 < tagFilters.length; t3++)
{
for(var t2=0; t2<tiddlerTags.length; t2++)
{
if (tagFilters[t3].length > 1 && tagFilters[t3].charAt(0) == '!')
{
if (tiddlerTags[t2] == tagFilters[t3].substring(1))
{
//If at any time a negative filter is matched, we return false
return false;
}
}
else
{
if (bNoPos)
{
//We encountered the first positive filter
bNoPos=false;
}
if (tiddlerTags[t2] == tagFilters[t3])
{
//A positive filter is matched. As long as no negative filter is matched, hasTag will return true
bHasTag=true;
}
}
}
}
return (bNoPos || bHasTag);
};
//This function searches all tiddlers for the reminder //macro. It is intended that other plugins (like //calendar) will use this function to query for
//upcoming reminders.
//The arguments to this function filter out reminders //based on when they will fire.
//
//ARGUMENTS:
//baseDate is the date that is used as "now".
//leadtime is a two element int array, with leadtime[0]
// as the lower bound and leadtime[1] as the
// upper bound. A reasonable default is [0,14]
//tags is a space-separated list of tags to use to filter
// tiddlers. If a tag name begins with an !, then
// only tiddlers which do not have that tag will
// be considered. For example "examples holidays"
// will search for reminders in any tiddlers that
// are tagged with examples or holidays and
// "!examples !holidays" will search for reminders
// in any tiddlers that are not tagged with
// examples or holidays. Pass in null to search
// all tiddlers.
//limit. If limit is null, individual reminders can
// override the leadtime specified earlier.
// Pass in 1 in order to override that behavior.
window.findTiddlersWithReminders = function findTiddlersWithReminders(baseDate, leadtime, tags, limit)
{
//function(searchRegExp,sortField,excludeTag)
// var macroPattern = "<<([^>\\]+)(?:\\*)([^>]*)>>";
var macroPattern = "<<(reminder)(.*)>>";
var macroRegExp = new RegExp(macroPattern,"mg");
var matches = store.search(macroRegExp,"title","");
var arr = [];
var tagsArray = null;
if (tags != null)
{
// tagsArray = tags.split(" ");
tagsArray = tags.readBracketedList(); // allows tags with spaces. thanks Robin Summerhill, 4-Oct-06.
}
for(var t=matches.length-1; t>=0; t--)
{
if (tagsArray != null)
{
//If they specified tags to filter on, and this tiddler doesn't
//match, skip it entirely.
if ( ! hasTag(matches[t].tags, tagsArray))
{
continue;
}
}
var targetText = matches[t].text;
do {
// Get the next formatting match
var formatMatch = macroRegExp.exec(targetText);
if(formatMatch && formatMatch[1] != null && formatMatch[1].toLowerCase() == "reminder")
{
//Find the matching date.
var params = formatMatch[2] != null ? formatMatch[2].readMacroParams() : {};
var dateHash = getParamsForReminder(params);
if (limit != null || dateHash["leadtime"] == null)
{
if (leadtime == null)
dateHash["leadtime"] = leadtime;
else
{
dateHash["leadtime"] = [];
dateHash["leadtime"][0] = leadtime[0];
dateHash["leadtime"][1] = leadtime[1];
}
}
if (dateHash["leadtime"] == null)
dateHash["leadtime"] = config.macros.reminders["defaultLeadTime"];
var leadTimeLowerBound = baseDate.addDays(dateHash["leadtime"][0]);
var leadTimeUpperBound = baseDate.addDays(dateHash["leadtime"][1]);
var matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);
while (matchedDate != null)
{
var hash = {};
hash["diff"] = matchedDate.getDifferenceInDays(baseDate);
hash["matchedDate"] = new Date(matchedDate.getFullYear(), matchedDate.getMonth(), matchedDate.getDate(), 0, 0);
hash["params"] = cloneParams(dateHash);
hash["tiddler"] = matches[t].title;
hash["tags"] = matches[t].tags;
arr.pushUnique(hash);
if (dateHash["recurdays"] != null || (dateHash["year"] == null))
{
leadTimeLowerBound = leadTimeLowerBound.addDays(matchedDate.getDifferenceInDays(leadTimeLowerBound)+ 1);
matchedDate = findDateForReminder(dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound);
}
else matchedDate = null;
}
}
}while(formatMatch);
}
if(arr.length > 1) //Sort the array by number of days remaining.
{
arr.sort(function (a,b) {if(a["diff"] == b["diff"]) {return(0);} else {return (a["diff"] < b["diff"]) ? -1 : +1; } });
}
return arr;
};
//This function takes the reminder macro parameters and
//generates the string that is used for display.
//This function is not intended to be called by
//other plugins.
window.getReminderMessageForDisplay= function getReminderMessageForDisplay(diff, params, matchedDate, tiddlerTitle)
{
var anniversaryString = "";
var reminderTitle = params["title"];
if (reminderTitle == null)
{
reminderTitle = config.macros.reminders["untitledReminder"];
}
if (params["firstyear"] != null)
{
anniversaryString = config.macros.reminders["defaultAnniversaryMessage"].replace("DIFF", (matchedDate.getFullYear() - params["firstyear"]));
}
var mess = "";
var diffString = "";
if (diff == 0)
{
diffString = config.macros.reminders["todayString"];
}
else if (diff == 1)
{
diffString = config.macros.reminders["tomorrowString"];
}
else
{
diffString = config.macros.reminders["ndaysString"].replace("DIFF", diff);
}
var format = config.macros.reminders["defaultReminderMessage"];
if (params["format"] != null)
{
format = params["format"];
}
mess = format;
//HACK! -- Avoid replacing DD in TIDDLER with the date
mess = mess.replace(/TIDDLER/g, "TIDELER");
mess = matchedDate.formatStringDateOnly(mess);
mess = mess.replace(/TIDELER/g, "TIDDLER");
if (tiddlerTitle != null)
{
mess = mess.replace(/TIDDLERNAME/g, tiddlerTitle);
mess = mess.replace(/TIDDLER/g, "[[" + tiddlerTitle + "]]");
}
mess = mess.replace("DIFF", diffString).replace("TITLE", reminderTitle).replace("DATE", matchedDate.formatString("DDD MMM DD, YYYY")).replace("ANNIVERSARY", anniversaryString);
return mess;
};
// Parse out the macro parameters into a hashtable. This
// handles the arguments for reminder, showReminders and
// displayTiddlersWithReminders.
window.getParamsForReminder = function getParamsForReminder(params)
{
var dateHash = {};
var type = "";
var num = 0;
var title = "";
for(var t=0; t<params.length; t++)
{
var split = params[t].split(":");
type = split[0].toLowerCase();
var value = split[1];
for (var i=2; i < split.length; i++)
{
value += ":" + split[i];
}
if (type == "nolinks" || type == "limit" || type == "hidden")
{
num = 1;
}
else if (type == "leadtime")
{
var leads = value.split("...");
if (leads.length == 1)
{
leads[1]= leads[0];
leads[0] = 0;
}
leads[0] = parseInt(leads[0], 10);
leads[1] = parseInt(leads[1], 10);
num = leads;
}
else if (type == "offsetdayofweek")
{
if (value.substr(0,1) == "-")
{
dateHash["negativeOffsetDayOfWeek"] = 1;
value = value.substr(1);
}
num = parseInt(value, 10);
}
else if (type != "title" && type != "tag" && type != "format")
{
num = parseInt(value, 10);
}
else
{
title = value;
t++;
while (title.substr(0,1) == '"' && title.substr(title.length - 1,1) != '"' && params[t] != undefined)
{
title += " " + params[t++];
}
//Trim off the leading and trailing quotes
if (title.substr(0,1) == "\"" && title.substr(title.length - 1,1)== "\"")
{
title = title.substr(1, title.length - 2);
t--;
}
num = title;
}
dateHash[type] = num;
}
//date is synonymous with day
if (dateHash["day"] == null)
{
dateHash["day"] = dateHash["date"];
}
return dateHash;
};
//This function finds the date specified in the reminder
//parameters. It will return null if no match can be
//found. This function is not intended to be used by
//other plugins.
window.findDateForReminder= function findDateForReminder( dateHash, baseDate, leadTimeLowerBound, leadTimeUpperBound)
{
if (baseDate == null)
{
baseDate = new Date().getMidnight();
}
var hashKey = baseDate.convertToYYYYMMDDHHMM();
for (var k in dateHash)
{
hashKey += "," + k + "|" + dateHash[k];
}
hashKey += "," + leadTimeLowerBound.convertToYYYYMMDDHHMM();
hashKey += "," + leadTimeUpperBound.convertToYYYYMMDDHHMM();
if (reminderCache[hashKey] == null)
{
//If we don't find a match in this run, then we will
//cache that the reminder can't be matched.
reminderCache[hashKey] = false;
}
else if (reminderCache[hashKey] == false)
{
//We've already tried this date and failed
return null;
}
else
{
return reminderCache[hashKey];
}
var bOffsetSpecified = dateHash["offsetyear"] != null ||
dateHash["offsetmonth"] != null ||
dateHash["offsetday"] != null ||
dateHash["offsetdayofweek"] != null ||
dateHash["recurdays"] != null;
// If we are matching the base date for a dayofweek offset, look for the base date a
//little further back.
var tmp1leadTimeLowerBound = leadTimeLowerBound;
if ( dateHash["offsetdayofweek"] != null)
{
tmp1leadTimeLowerBound = leadTimeLowerBound.addDays(-6);
}
var matchedDate = baseDate.findMatch(dateHash, tmp1leadTimeLowerBound, leadTimeUpperBound);
if (matchedDate != null)
{
var newMatchedDate = matchedDate;
if (dateHash["recurdays"] != null)
{
while (newMatchedDate.getTime() < leadTimeLowerBound.getTime())
{
newMatchedDate = newMatchedDate.addDays(dateHash["recurdays"]);
}
}
else if (dateHash["offsetyear"] != null ||
dateHash["offsetmonth"] != null ||
dateHash["offsetday"] != null ||
dateHash["offsetdayofweek"] != null)
{
var tmpdateHash = cloneParams(dateHash);
tmpdateHash["year"] = dateHash["offsetyear"];
tmpdateHash["month"] = dateHash["offsetmonth"];
tmpdateHash["day"] = dateHash["offsetday"];
tmpdateHash["dayofweek"] = dateHash["offsetdayofweek"];
var tmpleadTimeLowerBound = leadTimeLowerBound;
var tmpleadTimeUpperBound = leadTimeUpperBound;
if (tmpdateHash["offsetdayofweek"] != null)
{
if (tmpdateHash["negativeOffsetDayOfWeek"] == 1)
{
tmpleadTimeLowerBound = matchedDate.addDays(-6);
tmpleadTimeUpperBound = matchedDate;
}
else
{
tmpleadTimeLowerBound = matchedDate;
tmpleadTimeUpperBound = matchedDate.addDays(6);
}
}
newMatchedDate = matchedDate.findMatch(tmpdateHash, tmpleadTimeLowerBound, tmpleadTimeUpperBound);
//The offset couldn't be matched. return null.
if (newMatchedDate == null)
{
return null;
}
}
if (newMatchedDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
{
reminderCache[hashKey] = newMatchedDate;
return newMatchedDate;
}
}
return null;
};
//This does much the same job as findDateForReminder, but
//this one doesn't deal with offsets or recurring
//reminders.
Date.prototype.findMatch = function findMatch(dateHash, leadTimeLowerBound, leadTimeUpperBound)
{
var bSpecifiedYear = (dateHash["year"] != null);
var bSpecifiedMonth = (dateHash["month"] != null);
var bSpecifiedDay = (dateHash["day"] != null);
var bSpecifiedDayOfWeek = (dateHash["dayofweek"] != null);
if (bSpecifiedYear && bSpecifiedMonth && bSpecifiedDay)
{
return new Date(dateHash["year"], dateHash["month"]-1, dateHash["day"], 0, 0);
}
var bMatchedYear = !bSpecifiedYear;
var bMatchedMonth = !bSpecifiedMonth;
var bMatchedDay = !bSpecifiedDay;
var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;
if (bSpecifiedDay && bSpecifiedMonth && !bSpecifiedYear && !bSpecifiedDayOfWeek)
{
//Shortcut -- First try this year. If it's too small, try next year.
var tmpMidnight = this.getMidnight();
var tmpDate = new Date(this.getFullYear(), dateHash["month"]-1, dateHash["day"], 0,0);
if (tmpDate.getTime() < leadTimeLowerBound.getTime())
{
tmpDate = new Date((this.getFullYear() + 1), dateHash["month"]-1, dateHash["day"], 0,0);
}
if ( tmpDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
{
return tmpDate;
}
else
{
return null;
}
}
var newDate = leadTimeLowerBound;
while (newDate.isBetween(leadTimeLowerBound, leadTimeUpperBound))
{
var tmp = testDate(newDate, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek);
if (tmp != null)
return tmp;
newDate = newDate.addDays(1);
}
};
function testDate(testMe, dateHash, bSpecifiedYear, bSpecifiedMonth, bSpecifiedDay, bSpecifiedDayOfWeek)
{
var bMatchedYear = !bSpecifiedYear;
var bMatchedMonth = !bSpecifiedMonth;
var bMatchedDay = !bSpecifiedDay;
var bMatchedDayOfWeek = !bSpecifiedDayOfWeek;
if (bSpecifiedYear)
{
bMatchedYear = (dateHash["year"] == testMe.getFullYear());
}
if (bSpecifiedMonth)
{
bMatchedMonth = ((dateHash["month"] - 1) == testMe.getMonth() );
}
if (bSpecifiedDay)
{
bMatchedDay = (dateHash["day"] == testMe.getDate());
}
if (bSpecifiedDayOfWeek)
{
bMatchedDayOfWeek = (dateHash["dayofweek"] == testMe.getDay());
}
if (bMatchedYear && bMatchedMonth && bMatchedDay && bMatchedDayOfWeek)
{
return testMe;
}
};
//Returns true if the date is in between two given dates
Date.prototype.isBetween = function isBetween(lowerBound, upperBound)
{
return (this.getTime() >= lowerBound.getTime() && this.getTime() <= upperBound.getTime());
}
//Return a new date, with the time set to midnight (0000)
Date.prototype.getMidnight = function getMidnight()
{
return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0);
};
// Add the specified number of days to a date.
Date.prototype.addDays = function addDays(numberOfDays)
{
return new Date(this.getFullYear(), this.getMonth(), this.getDate() + numberOfDays, 0, 0);
};
//Return the number of days between two dates.
Date.prototype.getDifferenceInDays = function getDifferenceInDays(otherDate)
{
//I have to do it this way, because this way ignores daylight savings
var tmpDate = this.addDays(0);
if (this.getTime() > otherDate.getTime())
{
var i = 0;
for (i = 0; tmpDate.getTime() > otherDate.getTime(); i++)
{
tmpDate = tmpDate.addDays(-1);
}
return i;
}
else
{
var i = 0;
for (i = 0; tmpDate.getTime() < otherDate.getTime(); i++)
{
tmpDate = tmpDate.addDays(1);
}
return i * -1;
}
return 0;
};
function cloneParams(what) {
var tmp = {};
for (var i in what) {
tmp[i] = what[i];
}
return tmp;
}
// Substitute date components into a string
Date.prototype.formatStringDateOnly = function formatStringDateOnly(template)
{
template = template.replace("YYYY",this.getFullYear());
template = template.replace("YY",String.zeroPad(this.getFullYear()-2000,2));
template = template.replace("MMM",config.messages.dates.months[this.getMonth()]);
template = template.replace("0MM",String.zeroPad(this.getMonth()+1,2));
template = template.replace("MM",this.getMonth()+1);
template = template.replace("DDD",config.messages.dates.days[this.getDay()]);
template = template.replace("0DD",String.zeroPad(this.getDate(),2));
template = template.replace("DD",this.getDate());
return template;
};
//}}}
If you are like me, you like to reduce clutter and filesize as much as possible. Maybe there are features in ~TiddlyDu3 that you just won't use. Below are links to tiddlers, by feature, that can be removed without affecting other ~TiddlyDu3 functionality.
!Sample tiddlers
[[Test contact]]
[[Test task]]
[[Test project]]
[[Test goal]]
[[18 February 2009]]
!Instructions, GTD items, ~IFrames
The simplest way is to open TabHelp, TabGTD, and TabIFrames, then use the links there to open tiddlers you no longer wish to keep, and delete them. Then go back to TabHelp, TabGTD, and TabIFrames, and delete the dead links. To completely remove TabHelp, TabGTD, or TabIFrames, delete the tiddler, then delete the appropriate line in TabExtras.
!Info tab
If you don't think you would ever save bits and pieces of information in ~TiddlyDu3, delete TabInfo, then open MainMenu and delete the line {{{"Info" "Info" TabInfo}}}.
!Contacts
I personally don't use ~TiddlyWiki to store contacts. There are many much more efficient ways of storing and using contacts. I include it though, for completeness and because someone will at least want to keep some contact info at hand if they use ~TiddlyDu3. To remove this section:
*Delete ContactGroupSliderFrame, ContactgroupViewTemplate, NewContactTemplate, TabContacts and TabContactGroups.
*Delete TabContactsTab, and in MainMenu, delete the line {{{"Contacts" "Contacts" TabContactsTab}}}.
!Calendars and appointments
*The simplest way is to open TabCalendars, then use the links there to open tiddlers you no longer wish to keep, and delete them. Then go back to ~TabCalendars and delete the dead links. To completely remove ~TabCalendars, delete the tiddler, then delete the appropriate line in TabToDo.
*The plugins and background tiddlers used for calendars and appointments can be deleted too, if you don't plan to use any of the features of TabCalendars: CalendarPlugin, DatePlugin, [[Schedule]], [[AddActivity]], [[DatePluginConfig]], [[DatePickerLibrary]], [[CalendarYearSliderFrame]], [[CalendarPluginConfig]].
!Task types and statuses
The simplest way is to open TabTaskTypes, then use the links there to open tiddlers you no longer wish to keep, and delete them. Then go back to TabTaskTypes and delete the dead links. To completely remove ~TabTaskTypes, delete the tiddler, then delete the appropriate line in TabToDo. Statuses not showing in ~TabTaskTypes are [[Ongoing]], [[Possibly]], and [[Urgent]]. Just delete them from here.
!Goals, projects and tasks
You're using a personal organizer ~TiddlyWiki and you want to remove //these//? You need more help than I thought...
As you add the 'reporting' tag to your tasks, they will show up below. Use this list to keep track of tasks you need to report on for work reviews.
<<forEachTiddler where 'tiddler.tags.contains("Reporting")>>
/***
|Name|SaveAsPlugin|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPlugin|
|Version|1.0.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Save current document to a different path/filename|
!!!!!Documentation
<<<
Syntax: {{{<<saveAs>>}}}
<<saveAs>>
<<<
!!!!!Revisions
<<<
2008.04.12 [1.0.1] automatically add "saveAs" to backstage commands
2008.04.12 [1.0.0] initial release - derived from [[NewDocumentPlugin]]
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveAsPlugin= {major: 1, minor: 0, revision: 1, date: new Date(2008,4,12)};
config.macros.saveAs = {
label: "save as...",
prompt: "Save current document to a different path/file",
filePrompt: "Please select or enter a target path/filename",
defaultFilename: "new.html",
okmsg: "%0 tiddlers written to %1",
failmsg: "An error occurred while creating %0",
handler: function(place,macroName,params)
{ var btn=createTiddlyButton(place,this.label,this.prompt,this.go); },
go: function() {
// make sure we are local
if (window.location.protocol!="file:") {
alert(config.messages.notFileUrlError);
if (store.tiddlerExists(config.messages.saveInstructions))
story.displayTiddler(null,config.messages.saveInstructions);
return;
}
// get current saved file
var currPath=getLocalPath(window.location.href);
var original=loadFile(currPath);
if (!original) {
alert(config.messages.cantSaveError);
if (store.tiddlerExists(config.messages.saveInstructions))
story.displayTiddler(null,config.messages.saveInstructions);
return;
}
// get new target path/filename
var newPath=currPath;
var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\");
if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
var newFile=currPath.substr(newPath.length); // trim path
if (!newFile.length) newFile=config.macros.saveAs.defaultFilename;
var target=config.macros.saveAs.ask(config.macros.saveAs.filePrompt,newPath,newFile);
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+config.macros.saveAs.defaultFilename;
var link="file:///"+target.replace(/\\/g,'/'); // link for message text
// write target
if (saveFile(target,updateOriginal(original)))
var msg=config.macros.saveAs.okmsg.format([store.getTiddlers("title").length,target]);
else
var msg=config.macros.saveAs.failmsg.format([target]);
clearMessage(); displayMessage(msg,link);
},
ask: 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;
}
};
//}}}
//{{{
// automatically add saveAs to backstage
config.tasks.saveAs = {
text: "saveAs",
tooltip: config.macros.saveAs.prompt,
action: function(){ clearMessage(); config.macros.saveAs.go(); }
}
config.backstageTasks.splice(config.backstageTasks.indexOf("save")+1,0,"saveAs");
//}}}
/***
|Name:|SaveCloseTiddlerPlugin|
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0 ($Rev: 5502 $)|
|Date:|$Date: 2008-06-10 23:31:39 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
To use these you must add them to the tool bar in your EditTemplate
***/
//{{{
merge(config.commands,{
saveCloseTiddler: {
text: 'done/close',
tooltip: 'Save changes to this tiddler and close it',
handler: function(ev,src,title) {
var closeTitle = title;
var newTitle = story.saveTiddler(title,ev.shiftKey);
if (newTitle)
closeTitle = newTitle;
return config.commands.closeTiddler.handler(ev,src,closeTitle);
}
},
cancelCloseTiddler: {
text: 'cancel/close',
tooltip: 'Undo changes to this tiddler and close it',
handler: function(ev,src,title) {
// the same as closeTiddler now actually
return config.commands.closeTiddler.handler(ev,src,title);
}
}
});
//}}}
/***
|''Name''|Schedule|
|''Description''|Creates a rolling schedule displayed either as a timetable or an agenda.|
|''Author''|Michael Borck|
|''Version''|0.5.3|
|''Date''|7 Dec 2008|
|''Status''|@@beta@@|
|''Source''|http://schedule.tiddlyspot.com/|
|''Copyright''|2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''Requires''|ReminderMacros see http://remindermacros.tiddlyspot.com |
|''Optional''|DatePickerLibrary see http://svn.tiddlywiki.org/Trunk/contributors/SaqImtiaz/libraries/DatePicker.js <br> Sparklines http://www.tiddlywiki.com/coreplugins.html|
|''Feedback''|borck.m@gmail.com|
|''CoreVersion''|2.4|
|''Documentation''|See [[ScheduleInfo]] for usage <br> http://schedule.tiddlyspot.com for API|
|''Type''|Macro|
|''Keywords''|timetable, schedule, appointments, hard landscape, macro|
!!!Code
***/
//{{{
if (!version.extensions.schedule) {
version.extensions.schedule = {
major: 0,
minor: 5,
revision: 3,
date: new Date(2008, 7, 12),
source: "http://schedule.tiddlyspot.com/"
};
config.macros.schedule = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var args = paramString.parseParams(null, null, true);
switch (getParam(args, "view", "agenda")) {
case "timetable":
var timetable = new config.macros.schedule.Timetable(place, args);
delete timetable;
break;
case "agenda":
var agenda = new config.macros.schedule.Agenda(place, args);
delete agenda;
break;
default:
displayMessage("SchedulPlugin: error unkown schedule view");
}
}
};
config.macros.schedule.Schedule = function(place, args) {
this.place = place;
this.isShadow = (getParam(args, "shadow", "on") === "on");
this.step = parseInt(getParam(args, "step", 1), 10);
this.isSparks = getParam(args, "sparklines", undefined);
this.duration = parseInt(getParam(args, "duration", 7), 10);
this.span = parseInt(getParam(args, "span", 12), 10);
this.span = this.span > 24 ? 24 : this.span; // silently change!
this.today = new Date();
this.epoch = new Date(getParam(args, "date", new Date()));
this.hourFrom = parseInt(getParam(args, "hourFrom", this.today.getHours()), 10);
if (this.duration < 0) { // from the past?
this.epoch.addN(this.duration);
this.duration = -this.duration;
}
this.date = new Date(this.epoch); // epoch changes, save for reset
this.shading = new config.macros.schedule.Shadings(args);
this.events = new
config.macros.schedule.Events(getParam(args, "defTime", "09:00"));
this.eveningStart = getParam(args, "eveningStart", "18");
this.dayStart = getParam(args, "dayStart", "06");
this.control = createTiddlyElement(this.place, "div");
this.timeNow = this.today.getHHMM();
this.isPast = this.epoch.isBefore(this.today);
this.isToday = this.epoch.isEqual(this.today);
this.isWeekend = this.epoch.isWeekend();
this.nextPeriod = function(n) {
this.epoch.addN(n);
this.isPast = this.epoch.isBefore(this.today);
this.isToday = this.epoch.isEqual(this.today);
this.isWeekend = this.epoch.isWeekend();
};
this.isOutOfHours = function(hour) {
return String.zeroPad(hour, 2) >= this.eveningStart || String.zeroPad(hour, 2) <= this.dayStart;
};
this.showSparks = function(place, sparks, colorAsToday) {
var sparkDiv = createTiddlyElement(place, "div", "spark");
if (config.macros.sparkline) {
config.macros.sparkline.handler(sparkDiv, null, sparks);
var sparkGraph = sparkDiv.getElementsByTagName("span");
this.shading.styleBackground(sparkGraph[0], this.isWeekend, colorAsToday, false, this.isShadow);
var ticks = sparkGraph[0].getElementsByTagName("img");
for (var i = 0; i < ticks.length; i++) {
this.shading.styleAsBlock(ticks[i], this.isToday, false, false);
}
}
return sparkDiv;
};
this.addControls = function(that) {
var adjust = function(n) {
removeChildren(that.body);
that.date.addN(n);
that.epoch = new Date(that.date);
that.isPast = that.epoch.isBefore(that.today);
that.isToday = that.epoch.isEqual(that.today);
that.isWeekend = that.epoch.isWeekend();
that.make();
return false;
};
var fwdDay = function() {
return adjust(1);
};
var fwdDur = function() {
return adjust(that.duration);
};
var backDay = function() {
return adjust( - 1);
};
var backDur = function() {
return adjust( - that.duration);
};
var controls = createTiddlyElement(this.control, "div");
createTiddlyButton(controls, "<<", "-" + this.duration + " Days", backDur);
createTiddlyButton(controls, "<", "-1 Day", backDay);
createTiddlyButton(controls, ">", "+1 Day", fwdDay);
createTiddlyButton(controls, ">>", "+" + this.duration + " Days", fwdDur);
};
this.make = function() {
var endWant = this.hourFrom + this.span;
var start = endWant > 24 ? 0 : this.hourFrom;
var end = endWant > 24 ? endWant - 24 : endWant; //mod op error in TW
this.makeSchedule(start, end);
if (endWant > 24) { // We need a second table
this.nextPeriod( - this.duration);
this.makeSchedule(this.hourFrom, 24);
}
};
};
String.HHMM = function(hour, mins) {
return String.zeroPad(hour, 2) + ":" + String.zeroPad(mins, 2);
};
config.macros.schedule.Agenda = function(place, args) {
this.base = config.macros.schedule.Schedule;
this.base(place, args);
this.isSparks = this.isSparks ? this.isSparks === "on": true;
this.addControls(this);
this.body = createTiddlyElement(place, "div");
// from CalendarPlugin (thanks)
this.journalDateFmt = "YYYY/MMM/DD";
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];
}
}
for (var i = 0; i < this.duration; i += this.step) {
this.make();
this.nextPeriod(this.step);
}
};
config.macros.schedule.Agenda.prototype.makeSchedule = function(start, end) {
this.events.cache(this.epoch);
this.makeHeader(start, end);
var isActive = (this.timeNow <= start);
for (var i = 0; i < this.events.list.length; i++) {
var event = this.events.list[i];
if ((event.start >= String.HHMM(start, "00")) && (event.end <= String.HHMM(end, "00"))) {
var cell = createTiddlyElement(this.body, "div");
var link = createTiddlyLink(cell, event.tiddler, false);
var text = event.title ? event.title: event.tiddler;
link.appendChild(document.createTextNode(text));
if ((event.end < this.timeNow && this.isToday) || this.isPast) {
link.style.color = this.eventPast;
}
var hour = event.start.split(":")[0];
this.shading.styleBackground(cell, this.isWeekend || this.isOutOfHours(hour), this.isToday, isActive, this.isPast, this.isShadow);
}
}
};
config.macros.schedule.Agenda.prototype.makeHeader = function(start, end) {
var day = createTiddlyElement(this.body, "h3");
var text = this.epoch.formatString(this.journalDateFmt);
if (this.isSparks) {
var sparks = this.events.count(start, end, this.detail);
var graph = this.showSparks(day, sparks, false);
}
else {
graph = createTiddlyElement(day, "div", "spark");
}
createTiddlyLink(graph, text, true);
};
config.macros.schedule.Timetable = function(place, args) {
this.base = config.macros.schedule.Schedule;
this.base(place, args);
this.isSparks = this.isSparks ? (this.isSparks === "on") : false;
this.addControls(this);
this.table = createTiddlyElement(this.place, "table", null, "bordersOff", null);
this.wrap = createTiddlyElement(this.table, "tbody");
this.body = createTiddlyElement(this.wrap, "tr");
switch (getParam(args, "detail", "medium")) {
case "low":
this.detail = 60;
break;
case "high":
this.detail = 15;
break;
default:
this.detail = 30;
}
this.make();
};
config.macros.schedule.Timetable.prototype.makeSchedule = function(start, end) {
var cell = createTiddlyElement(this.body, "td"); // Holds 1st/only table
var table = createTiddlyElement(cell, "table", null, "bordersOff", null);
var body = createTiddlyElement(table, "tbody");
var row = createTiddlyElement(body, "tr");
this.makeHeader(row, start, end);
for (var i = 0; i < this.duration; i += this.step) {
row = createTiddlyElement(body, "tr");
this.makeDay(row, start, end);
this.nextPeriod(this.step);
}
};
config.macros.schedule.Timetable.prototype.makeHeader = function(head, start, end) {
createTiddlyElement(head, "td"); //cell above day names
for (var h = start; h < end; h++) {
for (var m = 0; m < 60; m += this.detail) {
var hour = String.zeroPad(h, 2);
var time = createTiddlyElement(head, "td", null, "bordersOff", m === 0 ? hour: "");
if ((hour < String.zeroPad(this.dayStart, 2)) || (hour > String.zeroPad(this.eveningStart, 2))) {
time.style.background = this.shading.outOfHours;
}
}
}
};
config.macros.schedule.Timetable.prototype.makeDay = function(day, start, end) {
var title = createTiddlyElement(day, "td", null, null, null);
var text = this.epoch.getDate() + " " + this.epoch.dayName();
createTiddlyElement(title, "p", null, null, text);
//var isActive = (this.timeNow <= start);
this.shading.styleBackground(title, this.isWeekend, this.isToday, true, this.isPast, this.isShadow);
this.events.cache(this.epoch);
this.events.sizeIndex(this.detail);
var sparks = []
for (var h = start; h < end; h++) {
sparks[h - start] = 0;
for (var m = 0; m < 60; m += this.detail) {
var startBdry = String.HHMM(h, m);
var mins = m + this.detail;
var next = mins === 60 ? h + 1 : h;
var endBdry = String.HHMM(next, (mins === 60 ? "00": mins));
this.events.addStarting(startBdry, endBdry);
sparks[h - start] += this.showActive(day, startBdry);
this.events.removeEnding(startBdry, endBdry);
}
}
if (this.isSparks) {
this.showSparks(title, sparks, this.isToday);
}
};
config.macros.schedule.Timetable.prototype.showActive = function(day, start) {
var count = 0;
var isActive = (this.timeNow <= start);
var slot = createTiddlyElement(day, "td", null, "bordersOff", null);
this.shading.styleBackground(slot, this.isOutOfHours(start) || this.isWeekend, this.isToday, isActive, this.isPast, this.isShadow);
for (var i = 0; i < this.events.index.length; i++) {
var p = createTiddlyElement(slot, "p", null, null, ".");
if (this.events.index[i]) {
count++;
p.title = this.events.list[this.events.index[i] - 1].title;
this.shading.styleAsBlock(p, this.isToday, isActive, this.isPast);
}
else { // fake empty entry so events 'line up'
p.style.visibility = "hidden";
}
}
return count;
};
config.macros.schedule.Events = function(time) {
this.defaultTime = time;
this.list = [];
this.index = [];
};
config.macros.schedule.Events.prototype.cache = function(epoch) {
this.list = [];
var items = findTiddlersWithReminders(epoch, [0, 1], null, 1);
var validTime = /(2[0-3]|[01][0-9]):[0-5][0-9]/g;
for (var i = 0; i < items.length; i++) {
if (items[i].diff < 1) { // today?
var event = {};
event.tiddler = items[i].tiddler;
event.title = items[i].params.title ? items[i].params.title: items[i].tiddler;
event.start = this.defaultTime;
event.end = this.defaultTime;
if (items[i].params.title) {
var m = items[i].params.title.match(validTime);
if (m) // found at least one valid time in title
{
event.start = m[0]; // first match is start time
event.end = m[1] ? m[1] : m[0];
}
}
this.list.push(event);
}
}
this.list = this.list.sort(function byStart(a, b) {
return a.start > b.start;
});
};
config.macros.schedule.Events.prototype.sizeIndex = function(detail) {
this.index = [];
var max = 0;
for (var h = 0; h < 24; h++) {
var clashes = 0;
for (var m = 0; m < 60; m += detail) {
var start = String.HHMM(h, m);
var next = ((m + detail) === 60 ? (h + 1) : h);
var end = String.HHMM(next, ((m + detail) === 60 ? "00": m + detail));
for (var i = 0; i < this.list.length; i++) {
var event = this.list[i];
if (event.start >= start && event.start < end) {
clashes++;
max = max < clashes ? clashes: max;
}
else if (event.end > start && event.end <= end) {
clashes--;
}
}
}
}
this.index.length = max;
};
config.macros.schedule.Events.prototype.addStarting = function(start, end) {
for (var i = 0; i < this.list.length; i++) {
if (this.list[i].start >= start && this.list[i].start < end) {
var j = 0;
while (j < this.index.length && !this.index.contains(i + 1)) {
if (!this.index[j]) // non zero true
{
this.index[j] = i + 1; // store non-zero!
}
j++;
}
}
}
};
config.macros.schedule.Events.prototype.removeEnding = function(start, end) {
for (var i = 0; i < this.list.length; i++) {
var eventEnd = this.list[i].end;
var eventStart = this.list[i].start;
if (isEnding(this.index)) {
this.index[this.index.indexOf(i + 1)] = 0;
}
}
function isEnding(index) {
return (((eventEnd > start && eventEnd <= end) || ((eventEnd === eventStart) && (eventEnd === start)) || ((eventEnd.split(":")[0] === 23) && (eventEnd === start))) && (index.contains(i + 1)));
};
};
config.macros.schedule.Events.prototype.count = function(start, end, detail) {
var sparks = [];
for (var h = start; h < end; h++) {
sparks[h - start] = 0;
for (var m = 0; m < 60; m += detail) {
var startBdry = String.HHMM(h, m);
var next = ((m + detail) === 60 ? (h + 1) : h);
var endBdry = String.HHMM(next, ((m + detail) === 60 ? "00": m + detail));
for (var i = 0; i < this.list.length; i++) {
var event = this.list[i];
if ((event.start >= startBdry && event.start < endBdry) || (event.start < startBdry && event.end > endBdry)) {
sparks[h - start]++;
}
else if (event.endBdry > start && event.end <= endBdry) {
sparks[h - start]--;
}
}
}
}
return sparks;
};
config.macros.schedule.Shadings = function(args) {
this.activeEvent = getParam(args, "activeEvent", "#ccf");
this.eventPast = getParam(args, "eventPast", "#edf");
this.outOfHours = getParam(args, "outOfHours", "#efe");
this.todayOOH = getParam(args, "todayOOH", "#eee");
this.todayFocus = getParam(args, "todayFocus", "#eef");
this.inPast = getParam(args, "inPast", "#eff");
this.inFocus = getParam(args, "inFocus", "#eef");
};
config.macros.schedule.Shadings.prototype.styleBackground = function(cell, isOutOfHours, isToday, isActive, isPast, isShadow) {
cell.style.background = "white";
if (isOutOfHours) {
cell.style.background = this.outOfHours;
}
if (isToday) {
cell.style.background = this.todayFocus;
}
if (isToday && isOutOfHours) {
cell.style.background = this.todayOOH;
}
if (isPast || (isToday && !isActive && isShadow)) {
cell.style.background = this.inPast;
}
};
config.macros.schedule.Shadings.prototype.styleAsBlock = function(block, isToday, isActive, isPast) {
if ((isToday && !isActive) || isPast) {
block.style.background = this.eventPast;
block.style.color = this.eventPast;
}
else // Must be an active event!
{
block.style.background = this.activeEvent;
block.style.color = this.activeEvent;
}
};
Date.prototype.isWeekend = function() {
return this.getDay() === 0 || this.getDay() === 6;
};
Date.prototype.getHHMM = function() {
return String.zeroPad(this.getHours(), 2) + ":" + String.zeroPad(this.getDate(), 2);
};
Date.prototype.dayName = function() {
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
return days[this.getDay()];
};
Date.prototype.isBefore = function(date) {
return this.formatString("YYYY/0MM/0DD") < date.formatString("YYYY/0MM/0DD");
};
Date.prototype.isEqual = function(date) {
return this.formatString("YYYY/MM/DD") === date.formatString("YYYY/MM/DD");
};
Date.prototype.addN = function(n) {
var oneDay = (1000 * 60 * 60 * 24); // Milliseconds in a day
this.setTime(this.getTime() + (n * oneDay));
};
setStylesheet(".viewer table.bordersOff, .viewer table.bordersOff * " + "{margin:1; cell-padding:0; border:0; padding:0;} .viewer " + "td.bordersOff {width: 24px; height: 24px;} .sparkline { " + "background: Yellow; } .sparktick { background: White; }", "schedule");
}
//}}}
config.options.chkSearchIncremental=false;
//{{{
window.reportSearchResults=function(text,matches)
{
var title=config.macros.search.reportTitle
var q = config.options.chkRegExpSearch ? "/" : "'";
var body="\n";
// numbered list of links to matching tiddlers
body+="\n<<<";
for(var t=0;t<matches.length;t++) {
var date=config.options.chkSearchByDate?(matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" "):"";
body+="\n# "+date+"[["+matches[t].title+"]]";
}
body+="\n<<<\n";
// create/update the tiddler
var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();
tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch");
store.addTiddler(tiddler); story.closeTiddler(title);
// use alternate "search again" label in <<search>> macro
var oldprompt=config.macros.search.label;
config.macros.search.label="search again";
// render/refresh tiddler
story.displayTiddler(null,title,1);
store.notify(title,true);
// restore standard search label
config.macros.search.label=oldprompt;
}
//}}}
/***
|Name|SearchOptionsPlugin|
|Source|http://www.TiddlyTools.com/#SearchOptionsPlugin|
|Documentation|http://www.TiddlyTools.com/#SearchOptionsPluginInfo|
|Version|2.6.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.search, TiddlyWiki.prototype.search, config.macros.search.onKeyPress|
|Description|extend core search function with additional user-configurable options|
Extend core search function with additional user-configurable options including generating a ''list of matching tiddlers'' instead of immediately displaying all matches.
!!!!!Documentation
>see [[SearchOptionsPluginInfo]]
!!!!!Configuration
<<<
<<option chkSearchTitles>> Search in titles
<<option chkSearchText>> Search in tiddler text
<<option chkSearchTags>> Search in tags
<<option chkSearchFields>> Search in data fields
<<option chkSearchShadows>> Search shadow tiddlers
<<option chkSearchTitlesFirst>> Show title matches first
<<option chkSearchByDate>> Sort matching tiddlers by date
<<option chkSearchList>> Show list of matches in [[SearchResults]]
<<option chkSearchIncremental>> Incremental (key-by-key) searching
<<<
!!!!!Revisions
<<<
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
|please see [[SearchOptionsPluginInfo]] for additional revision details|
2005.10.18 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.searchOptions = {major: 2, minor: 6, revision: 1, date: new Date(2007,2,17)};
if (config.options.chkSearchTitles===undefined) config.options.chkSearchTitles=true;
if (config.options.chkSearchText===undefined) config.options.chkSearchText=true;
if (config.options.chkSearchTags===undefined) config.options.chkSearchTags=true;
if (config.options.chkSearchFields===undefined) config.options.chkSearchFields=true;
if (config.options.chkSearchTitlesFirst===undefined) config.options.chkSearchTitlesFirst=false;
if (config.options.chkSearchList===undefined) config.options.chkSearchList=false;
if (config.options.chkSearchByDate===undefined) config.options.chkSearchByDate=false;
if (config.options.chkSearchIncremental===undefined) config.options.chkSearchIncremental=true;
if (config.options.chkSearchShadows===undefined) config.options.chkSearchShadows=false;
if (config.optionsDesc) {
config.optionsDesc.chkSearchTitles="Search in tiddler titles";
config.optionsDesc.chkSearchText="Search in tiddler text";
config.optionsDesc.chkSearchTags="Search in tiddler tags";
config.optionsDesc.chkSearchFields="Search in tiddler data fields";
config.optionsDesc.chkSearchShadows="Search in shadow tiddlers";
config.optionsDesc.chkSearchTitlesFirst="Search results show title matches first";
config.optionsDesc.chkSearchList="Search results show list of matching tiddlers";
config.optionsDesc.chkSearchByDate="Search results sorted by modification date ";
config.optionsDesc.chkSearchIncremental="Incremental searching";
} else {
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSearchTitles>> Search in tiddler titles"
+"\n<<option chkSearchText>> Search in tiddler text"
+"\n<<option chkSearchTags>> Search in tiddler tags"
+"\n<<option chkSearchFields>> Search in tiddler data fields"
+"\n<<option chkSearchShadows>> Search in shadow tiddlers"
+"\n<<option chkSearchTitlesFirst>> Search results show title matches first"
+"\n<<option chkSearchList>> Search results show list of matching tiddlers"
+"\n<<option chkSearchByDate>> Search results sorted by modification date"
+"\n<<option chkSearchIncremental>> Incremental searching";
}
if (config.macros.search.reportTitle==undefined)
config.macros.search.reportTitle="SearchResults";
config.macros.search.onKeyPress = function(e)
{
if(!e) var e = window.event;
switch(e.keyCode)
{
case 13: // Ctrl-Enter
case 10: // Ctrl-Enter on IE PC
config.macros.search.doSearch(this);
break;
case 27: // Escape
this.value = "";
clearMessage();
break;
}
if (config.options.chkSearchIncremental) {
if(this.value.length > 2)
{
if(this.value != this.getAttribute("lastSearchText"))
{
if(config.macros.search.timeout)
clearTimeout(config.macros.search.timeout);
var txt = this;
config.macros.search.timeout = setTimeout(function() {config.macros.search.doSearch(txt);},500);
}
}
else
{
if(config.macros.search.timeout)
clearTimeout(config.macros.search.timeout);
}
}
}
//}}}
//{{{
Story.prototype.search = function(text,useCaseSensitive,useRegExp)
{
highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
var matches = store.search(highlightHack,config.options.chkSearchByDate?"modified":"title","excludeSearch");
if (config.options.chkSearchByDate) matches=matches.reverse(); // most recent changes first
var q = useRegExp ? "/" : "'";
clearMessage();
if (!matches.length) {
if (config.options.chkSearchList) discardSearchResults();
displayMessage(config.macros.search.failureMsg.format([q+text+q]));
} else {
if (config.options.chkSearchList)
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;
}
TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
{
var candidates = this.reverseLookup("tags",excludeTag,false,sortField);
// scan for matching titles first...
var results = [];
if (config.options.chkSearchTitles) {
for(var t=0; t<candidates.length; t++)
if(candidates[t].title.search(searchRegExp)!=-1)
results.push(candidates[t]);
if (config.options.chkSearchShadows)
for (var t in config.shadowTiddlers)
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<candidates.length; t++) {
if (config.options.chkSearchText && candidates[t].text.search(searchRegExp)!=-1)
results.pushUnique(candidates[t]);
if (config.options.chkSearchTags && candidates[t].tags.join(" ").search(searchRegExp)!=-1)
results.pushUnique(candidates[t]);
if (config.options.chkSearchFields && store.forEachField!=undefined) // requires TW2.1 or above
store.forEachField(candidates[t],
function(tid,field,val) { if (val.search(searchRegExp)!=-1) results.pushUnique(candidates[t]); },
true); // extended fields only
}
// then check for matching text in shadows
if (config.options.chkSearchShadows)
for (var t in config.shadowTiddlers)
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 (!config.options.chkSearchTitlesFirst || config.options.chkSearchByDate) results.sort(bySortField);
return results;
}
// REPORT GENERATOR
if (!window.reportSearchResults) window.reportSearchResults=function(text,matches)
{
var title=config.macros.search.reportTitle
var q = config.options.chkRegExpSearch ? "/" : "'";
var body="\n";
// summary: nn tiddlers found matching '...', options used
body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\n";
body+="^^//searched in:// ";
body+=(config.options.chkSearchTitles?"''titles'' ":"");
body+=(config.options.chkSearchText?"''text'' ":"");
body+=(config.options.chkSearchTags?"''tags'' ":"");
body+=(config.options.chkSearchFields?"''fields'' ":"");
body+=(config.options.chkSearchShadows?"''shadows'' ":"");
if (config.options.chkCaseSensitiveSearch||config.options.chkRegExpSearch) {
body+=" //with options:// ";
body+=(config.options.chkCaseSensitiveSearch?"''case sensitive'' ":"");
body+=(config.options.chkRegExpSearch?"''text patterns'' ":"");
}
body+="^^";
// numbered list of links to matching tiddlers
body+="\n<<<";
for(var t=0;t<matches.length;t++) {
var date=config.options.chkSearchByDate?(matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" "):"";
body+="\n# "+date+"[["+matches[t].title+"]]";
}
body+="\n<<<\n";
// open all matches button
body+="<html><input type=\"button\" href=\"javascript:;\" ";
body+="onclick=\"story.displayTiddlers(null,["
for(var t=0;t<matches.length;t++)
body+="'"+matches[t].title.replace(/\'/mg,"\\'")+"'"+((t<matches.length-1)?", ":"");
body+="],1);\" ";
body+="accesskey=\"O\" ";
body+="value=\"open all matching tiddlers\"></html> ";
// discard search results button
body+="<html><input type=\"button\" href=\"javascript:;\" ";
body+="onclick=\"story.closeTiddler('"+title+"'); store.deleteTiddler('"+title+"'); store.notify('"+title+"',true);\" ";
body+="value=\"discard "+title+"\"></html>";
// search again
body+="\n\n----\n";
body+="<<search \""+text+"\">>\n";
body+="<<option chkSearchTitles>>titles ";
body+="<<option chkSearchText>>text ";
body+="<<option chkSearchTags>>tags";
body+="<<option chkSearchFields>>fields";
body+="<<option chkSearchShadows>>shadows";
body+="<<option chkCaseSensitiveSearch>>case-sensitive ";
body+="<<option chkRegExpSearch>>text patterns";
body+="<<option chkSearchByDate>>sort by date";
// create/update the tiddler
var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();
tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch temporary");
store.addTiddler(tiddler); story.closeTiddler(title);
// use alternate "search again" label in <<search>> macro
var oldprompt=config.macros.search.label;
config.macros.search.label="search again";
// render/refresh tiddler
story.displayTiddler(null,title,1);
store.notify(title,true);
// restore standard search label
config.macros.search.label=oldprompt;
}
if (!window.discardSearchResults) window.discardSearchResults=function()
{
// remove the tiddler
story.closeTiddler(config.macros.search.reportTitle);
store.deleteTiddler(config.macros.search.reportTitle);
}
//}}}
//{{{
window.reportSearchResults=function(text,matches)
{
var title=config.macros.search.reportTitle
var q = config.options.chkRegExpSearch ? "/" : "'";
var body="\n";
// numbered list of links to matching tiddlers
body+="\n<<<";
for(var t=0;t<matches.length;t++) {
var date=config.options.chkSearchByDate?(matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" "):"";
body+="\n# "+date+"[["+matches[t].title+"]]";
}
body+="\n<<<\n";
// create/update the tiddler
var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();
tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch");
store.addTiddler(tiddler); story.closeTiddler(title);
// use alternate "search again" label in <<search>> macro
var oldprompt=config.macros.search.label;
config.macros.search.label="search again";
// render/refresh tiddler
story.displayTiddler(null,title,1);
store.notify(title,true);
// restore standard search label
config.macros.search.label=oldprompt;
}
//}}}
<<forEachTiddler where 'tiddler.tags.contains("Shop, out")' sortBy 'tiddler.title'>>
@@padding-left:0.7em;font-size:9px;color:#aaa;TW Ver:<<version>>@@<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "YYYY.0MM.0DD at 0hh:0mm:0ss">><<saveChanges>><<doBackup>><<tiddler TspotSidebar>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
@@padding:0.6em;<<slider chkSliderSidebarTabs SliderSidebarTabs 'indexes »'>>@@
/***
| Name:|SiteMapMacro|
| Author:|Simon Baird|
| Location:|http://simonbaird.com/mptw/#SiteMapMacro|
| Version:|1.0.3, 15-Mar-06|
!!Examples
See SiteMap and SliderSiteMap for example usage.
!!Parameters
* Name of tiddler to start at
* Max depth (a number)
* Format (eg, nested, see formats below)
* Don't show root flag (anything other than null turns it on)
* Tags - a string containing a bracketed list of tags that we are interested in
!!History
* 1.0.3 (15-Mar-06)
** added tag filtering
* 1.0.2 (15-Mar-06)
** Added json format and dontshowroot option
* 1.0.1 (9-Mar-06)
** Added selectable formats and fixed nested slider format
* 1.0.0 (8-Mar-06)
** first release
***/
//{{{
version.extensions.SiteMapMacro = {
major: 1,
minor: 0,
revision: 3,
date: new Date(2006,3,15),
source: "http://simonbaird.com/mptw/#SiteMapMacro"
};
config.macros.siteMap = {
formats: {
bullets: {
formatString: "%0[[%1]]\n%2",
indentString: "*"
},
// put this in your StyleSheet to make it look good.
// .sliderPanel { margin-left: 2em; }
sliders: {
formatString: "[[%1]]+++\n%2===\n\n",
formatStringLeaf: "[[%1]]\n"
},
openSliders: {
formatString: "[[%1]]++++\n%2===\n\n",
formatStringLeaf: "[[%1]]\n"
},
popups: {
formatString: "[[%1]]+++^\n%2===\n\n",
formatStringLeaf: "[[%1]]\n"
},
// these don't work too well
openPopups: {
formatString: "[[%1]]++++^\n%2===\n\n",
formatStringLeaf: "[[%1]]\n"
},
// this is a little nuts but it works
json: {
formatString: '\n%0{"%1":[%2\n%0]}',
formatStringLeaf: '\n%0"%1"',
indentString: " ",
separatorString: ","
}
},
defaultFormat: "bullets",
treeTraverse: function(title,depth,maxdepth,format,dontshowroot,tags,excludetags) {
var tiddler = store.getTiddler(title);
var tagging = store.getTaggedTiddlers(title);
if (dontshowroot)
depth = 0;
var indent = "";
if (this.formats[format].indentString)
for (var j=0;j<depth;j++)
indent += this.formats[format].indentString;
var childOutput = "";
if (!maxdepth || depth < parseInt(maxdepth))
for (var i=0;i<tagging.length;i++)
if (tagging[i].title != title) {
if (this.formats[format].separatorString && i != 0)
childOutput += this.formats[format].separatorString;
childOutput += this.treeTraverse(tagging[i].title,depth+1,maxdepth,format,null,tags,excludetags);
}
if (childOutput == "" && (
(tags && tags != "" && !tiddler.tags.containsAll(tags.readBracketedList())) ||
(excludetags && excludetags != "" && tiddler.tags.containsAny(excludetags.readBracketedList()))
)
) {
// so prune it cos it doesn't have the right tags and neither do any of it's children
return "";
}
if (dontshowroot)
return childOutput;
if (this.formats[format].formatStringLeaf && childOutput == "") {
// required for nestedSliders
return this.formats[format].formatStringLeaf.format([indent,title,childOutput]);
}
return this.formats[format].formatString.format([indent,title,childOutput]);
},
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
wikify(this.treeTraverse(
params[0] && params[0] != '.' ? params[0] : tiddler.title, 1,
params[1] && params[1] != '.' ? params[1] : null, // maxdepth
params[2] && params[2] != '.' ? params[2] : this.defaultFormat, // format
params[3] && params[3] != '.' ? params[3] : null, // dontshowroot
params[4] && params[4] != '.' ? params[4] : null, // tags
params[5] && params[5] != '.' ? params[5] : null // excludetags
),place);
}
}
//}}}
@@font-size:16pt;TW ~TuDu@@
http://twtudu.tiddlyspot.com/
<<siteMap [[Enter the name for your new sub-topic here, too]] . sliders>>
<<tabs txtMainTab "Timeline" "Timeline" TabTimeline "All" "All tiddlers" TabAll "Tags" "All tags" TabTags "More" "More lists" TabMore>>
<<forEachTiddler where 'tiddler.tags.contains("Someday/Maybe")>>
When you create a new task and go to view mode, you will have the option of setting the task's status and type. Tagging a task's statuses or types places it in indexes in the Task types tab.
*''Statuses'' are a way to flag tasks as urgent, waiting for something, etc. Here are all the statuses and their uses:
**''Ongoing'': This status is for tasks that need to be done every day or week. Tasks tagged as ongoing show up in the Current tiddler in the ongoing box.
**''Possibly'': This status is for tasks that are not urgent, but you may decide to do them this week if you have the time and energy. Tasks tagged as Possibly show up in the Current tiddler in the possibly box.
**''Reporting'': This status is for tasks you have done, but still need to be reported on for your next work review.
**''Someday/Maybe'': This status is for possibilities you may decide to think through and/or act upon sometime in the future. Tagging a task as urgent places it in the Someday/Maybe tiddler.
**''Urgent'': This status is for tasks that must be done right away. Tagging a task as urgent places it in the Current tiddler in the Urgent box.
**''Waiting'': This status is for tasks waiting for someone or something before they can be acted on. Tagging a task as waiting places it in the Waiting tiddler and in the Current tiddler in the Waiting box.
*''Task types'' is an optional way of organizing your tasks. If you're in the mood to do a number of similar tasks, just click on the index for that task type to see a list of possibilities.
/*FONT STUFF*/
body {font-family: arial; font-size: 10pt;}
.header {position:relative; height:40px;}
.uparrow{ font-weight: bold; text-decoration: underline; padding-right: 7px; background: url(http://img408.imageshack.us/img408/5150/daquo3gq1.gif) no-repeat right 56%; }
h1,h2,h3,h4,h5 { color: #8899ff; background: white; font-family: Verdana; border-bottom: none;}
.editor a {color:#dddddd;}
#editor a {color:#dddddd;}
.nowrap { white-space:nowrap;}
hr {border: 0px;border-top: solid 1px #c06;color: #c06;width:100%;}
.viewer hr {border: 0px;border-top: solid 1px #c06;color: #c06;width:100%;}
.appta a {font-size:.75em;color:#555;font-weight:bold;}
.unboldlink a {font-weight:normal;}
.toolbar a {color:#5566ff;}
.selected .toolbar a {color:#5566ff;}
.selected .toolbar a:hover {color:#5566ff;}
.popup li {list-style:none;}
.doubleborder {
border: 4px double #a00;
padding:1px;
margin: 8px;
width:132px;
height:99px;
}
#tiddlerTWHelp-SearchResults .viewer {
overflow: auto;
}
/* SHORTENS THE HEIGHT OF THE HEADER */
#displayArea {margin-top:0.0em}
.header {position:relative; height:45px;}
.headerShadow {padding: 1.4em 0em .8em 1em;}
.headerForeground {padding: 1.4em 0em .8em 1em;}
.siteTitle {font-size:1.0em;}
.siteSubtitle {font-size:1em;}
.siteTitle {font-size:1.0em;}
.siteSubtitle {font-size:1em;}
/*MAINMENU*/
#mainMenu {width: 17.5em; text-align: left; font-size: .85em;}
#displayArea {margin: 0em 14.5em 0em 16.5em;}
#mainMenu .sliderPanel { margin-left: 1.2em; }
#mainMenu .tiddlyLinkExisting {font-weight: bold;}
.bluey a {color: #900;}
.bluey {font-weight: bold; color: #900; font-size: 1.3em;}
.viewer .sliderPanel { margin-left: 1.2em; }
.sliderPanel { margin-left: 1em; }
/*TABLE HEADER*/
.viewer th {color: #000; background-color: #eeeeee;}
/*TIDDLER TOPMARGIN AND BUTTON BORDER*/
/*.viewer .button{border:solid 0px;color:#c06;}
.viewer a {border: solid 1px;}*/
.viewer a.button{color:#008;border: solid 1px #008;background:url("http://img520.imageshack.us/img520/8688/mainmenugray7ef.gif") repeat-x top left;top left;-moz-border-radius: .2em;}
.button {border: solid 0px;}
.makeborder {border: solid 1px #008;padding-left: 2px;padding-right: 2px; background:url("http://img520.imageshack.us/img520/8688/mainmenugray7ef.gif") repeat-x top left;top left;-moz-border-radius: .2em;}
.viewer { margin-top: .5em; }
.viewer {line-height: 1.4em;}
.viewer {line-height: 1.4em;}
/*Links*/
a:hover{background:#fff;color:#f00;}
/*TIDDLER TITLE COLOR MATCH BOTTOM OF HEADER*/
.title {color:#a00;}
/*UNORDERED and ORDERED LISTS TWEAK*/
.viewer li {padding-top: 0.2em; padding-bottom: 0.2em;}
/*LINELESS BLOCKQUOTES*/
.viewer blockquote {border-left: 10px; margin-top:0em; margin-bottom:0em; }
/*INVISIBLE TABLE*/
.viewer .invisiblecomm table {border-color: white;}
.viewer .invisiblecomm table td { font-size: 1em; font-family: Verdana; border-color: white; padding: 10px 20px 10px 0px; text-align: left; vertical-align: top; padding: 20px;}
.viewer .invisiblecomm table th { color: #005566; background-color: white; border-color: white; font-family: Verdana; font-size: 1.2em; font-weight: bold; padding: 10px 20px 10px 0px; text-align: left; vertical-align: top;}
.viewer .invisiblecomm table tr.leftColumn { background-color: #bbbbbb; }
/*TOPMENU*/
#topMenu {padding-left: 0em; background-color: #900; color: #110077; font-family: Trebuchet MS, Verdana; font-size: 13pt; line-height: 1.4em;}
#topMenu table td {margin: 10px;}
#topMenu .purple a {color: #0055dd;}
/*ROUNDED CORNERS AND BORDERS*/
.tiddler {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-bottom: 3px solid #ccc;
border-right: 3px solid #ccc;
margin: 0.5em;
background:#fff;
padding: 0.5em;
-moz-border-radius: 1em; }
#messageArea {
background-color: #eee;
border-color: #8ab;
border-width: 4px;
border-style: dotted;
font-size: 90%;
padding: 0.5em;
-moz-border-radius: 1em; }
/*TagglyTag styles*/
.tagglyTagged li.listTitle { display:none;}
.tagglyTagged li { display: inline; font-size:90%; }
.tagglyTagged ul { margin:0px; padding:0px; }
.tagglyTagging { padding-top:0.5em; }
.tagglyTagging li.listTitle { display:none;}
.tagglyTagging ul { margin-top:0px; padding-top:0.5em; padding-left:0em; margin-bottom:0px; padding-bottom:0px; }
/* .tagglyTagging .tghide { display:inline; } */
.tagglyTagging { vertical-align: top; margin:0px; padding:0px; }
.tagglyTagging table { margin:0px; padding:0px; }
.tagglyTagging .button { display:none; margin-left:3px; margin-right:3px; }
.tagglyTagging .button, .tagglyTagging .hidebutton { color:#aaa; font-size:90%; border:0px; padding-left:0.3em;padding-right:0.3em;}
.tagglyTagging .button:hover, .hidebutton:hover { background:#eee; color:#888; }
.selected .tagglyTagging .button { display:inline; }
.tagglyTagging .hidebutton { color:white; } /* has to be there so it takes up space. tweak if you're not using a white tiddler bg */
.selected .tagglyTagging .hidebutton { color:#aaa }
.tagglyLabel { color:#aaa; font-size:90%; }
.tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }
.tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}
.tagglyTagging ul ul li {margin-left:0.5em; }
.editLabel { font-size:90%; padding-top:0.5em; }
/* GIFFMEX TWEAKS TO STYLESHEETPRINT (so that nothing but tiddler title and text are printed) */
@media print {#mainMenu {display: none ! important;}}
@media print {#topMenu {display: none ! important;}}
@media print {#sidebar {display: none ! important;}}
@media print {#messageArea {display: none ! important;}}
@media print {#toolbar {display: none ! important;}}
@media print {.header {display: none ! important;}}
@media print {.tiddler .subtitle {display: none ! important;}}
@media print {.tiddler .toolbar {display; none ! important; }}
@media print {.tiddler .tagging {display; none ! important; }}
@media print {.tiddler .tagged {display; none ! important; }}
@media print {#displayArea {margin: 1em 1em 0em 1em;}}
@media print {.pageBreak {page-break-before: always;}}
/*COLUMNS*/
.twocolumns { display:block; -moz-column-count:2; -moz-column-gap:1em; -moz-column-
width:50%;}
.threecolumns { display:block; -moz-column-count:3; -moz-column-gap:1em; -moz-column-
width:33%}
.fourcolumns { display:block; -moz-column-count:4; -moz-column-gap:1em; -moz-column-
width:25%}
.popup li .tagger a {display:inline;}
/*{{{*/
.popup {
max-height:275px;
min-height:auto;
width: 300;
overflow: auto;
margin:auto;
font-family: arial; font-size: 10pt;
}
.headline{
color:#c06;
font-size:180%;
font-family:times,arial;
line-height:60%;
}
.textleft { display:block;text-align:left; }
.textright { display:block;text-align:right; }
.textcenter { display:block;text-align:center; }
.textjustify { display:block;text-align:justify; }
.textindent { display:block;margin:0;padding:0;border:0;margin-left:2em; }
/%.viewer .popup li { display:block;font-size:90%; white-space:nowrap;}%/
/***
!!!<<gradient horiz #fc3 #fff >><<tiddler RefreshStyles>> ButtonStyle>>/%==================================================%/
***/
input.btn{
color:#008;
font-family:Trebuchet MS,aerial,helvetica,sans-serif;
font-size:100%;
font-weight:normal;
background-color:#eee;
background:url("http://img520.imageshack.us/img520/8688/mainmenugray7ef.gif") repeat-x top left;top left;
border:1px solid;
border-top-color:#009;
border-left-color:#009;
border-right-color:#009;
border-bottom-color:#009;
-moz-border-radius : .25em 0.25em 0.25em 0.25em;
}
input.btnhov{
color:#a00;
background:#fff;
background:url("http://img520.imageshack.us/img520/8688/mainmenugray7ef.gif") repeat-x top left;top left;
border-top-color:#c06;
border-left-color:#c06;
border-right-color:#c06;
border-bottom-color:#c06;
-moz-border-radius : .25em 0.25em 0.25em 0.25em;
}
/*}}}*/
[[TabsCSS]]
[[StyleSheetTiddlersBar]]
[[StyleSheetShortcuts]]
[[TopMenuStyle]]
/*{{{*/
/*FONT STUFF*/
body {font-family: Calibri, arial, helvetica; font-size: 13pt;}
h1,h2,h3,h4,h5 { color: #8899ff; background: white; font-family: Calibri; border-bottom: none;}
.editor a {color:#dddddd;}
#editor a {color:#dddddd;}
.nowrap { white-space:nowrap;}
/*UNORDERED and ORDERED LISTS TWEAK*/
.viewer li {padding-top: 0.5em; padding-bottom: 0.5em;}
/*LINELESS BLOCKQUOTES*/
.viewer blockquote {border-left: 0px; margin-top:0em; margin-bottom:0em; }
/* HEADER */
.headerShadow {padding: .6em 0em .4em .6em;}
.headerForeground {padding: .6em 0em .4em .6em; text-align: center;}
.siteTitle {font-size: 1.5em; color: #aabbff;}
.siteSubtitle {font-size: 1em;}
.header .externalLink {text-decoration: none; color: #aabbff;}
.centeredmenu {padding: 7px; text-align:center;}
.headerForeground {position:relative;}
/*MAINMENU*/
#mainMenu {width: 19em; text-align: left; font-size: 11pt;}
#displayArea {margin: 0em 17.5em 0em 17em;}
.sliderPanel { margin-left: 1em; }
#mainMenu {padding: 0.2em 0.2em 0.2em 0.2em;}
.txtMenuMenu .tabContents li {list-style:none;}
.txtMenuMenu .invisiblecomm table tr.leftColumn { background-color: #bbbbbb; }
.txtMenuMenu .invisiblecomm table {border-color: #bbbbbb;}
.txtMenuMenu .invisiblecomm table td { font-size: .8em; font-family: Verdana; border-color: #bbbbbb; text-align: left; vertical-align: top; padding: 5px;}
.txtMenuMenu .invisiblecomm table tr.leftColumn { background-color: #bbbbbb; }
/*TIDDLER & VIEWTEMPLATE*/
.viewer a.button{border: 0;}
.viewer { margin-top: .1em; }
.viewer {line-height: 1.5em;}
.title {color:[[ColorPalette::PrimaryMid]];}
.historytool .macro {color:#dddddd;}
.toolbar a {color:#5566ff;}
.selected .toolbar a {color:#5566ff;}
.selected .toolbar a:hover {color:#5566ff;}
.toolbar .newbutton a {color:#888888; text-align: left; padding-right: .5em;}
/*TABLES*/
.viewer th {color: #000; background-color: #eeeeee;}
.viewer .invisiblecomm table {border-color: white;}
.viewer .invisiblecomm table td { font-size: 1em; font-family: Verdana; border-color: white; padding: 10px 20px 10px 0px; text-align: left; vertical-align: top; padding: 20px;}
.viewer .invisiblecomm table th { color: #005566; background-color: white; border-color: white; font-family: Verdana; font-size: 1.2em; font-weight: bold; padding: 10px 20px 10px 0px; text-align: left; vertical-align: top;}
/*TOPMENU*/
#topMenu {background-color: #aabbff; color: #110077; font-family: Trebuchet MS; font-size: 11pt; line-height: 2em; text-align: center;}
#topMenu table td {margin: 3px;}
#topMenu .purple a {color: #0055dd;}
#topMenu a {font-weight: bold;}
/*TOPMENU2*/
#topMenu2 {background-color: #ddddff; color: #110077; font-family: Trebuchet MS; font-size: 11pt; line-height: 2em; text-align: center;}
#topMenu2 table td {margin: 3px;}
#topMenu2 .purple a {color: #0055dd;}
#topMenu2 .button {border: #0055dd;}
/*ROUNDED CORNERS AND BORDERS*/
.tiddler {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-bottom: 3px solid #ccc;
border-right: 3px solid #ccc;
margin: 0.5em;
background:#fff;
padding: 0.5em;
-moz-border-radius: 1em; }
#messageArea {
background-color: #eee;
border-color: #8ab;
border-width: 4px;
border-style: dotted;
font-size: 90%;
padding: 0.5em;
-moz-border-radius: 1em; }
/*TagglyTag styles*/
.tagglyTagged li.listTitle { display:none;}
.tagglyTagged li { display: inline; font-size:90%; }
.tagglyTagged ul { margin:0px; padding:0px; }
.tagglyTagging { padding-top:0.5em; }
.tagglyTagging li.listTitle { display:none;}
.tagglyTagging ul { margin-top:0px; padding-top:0.5em; padding-left:2em; margin-bottom:0px; padding-bottom:0px; }
/* .tagglyTagging .tghide { display:inline; } */
.tagglyTagging { vertical-align: top; margin:0px; padding:0px; }
.tagglyTagging table { margin:0px; padding:0px; }
.tagglyTagging .button { display:none; margin-left:3px; margin-right:3px; }
.tagglyTagging .button, .tagglyTagging .hidebutton { color:#aaa; font-size:90%; border:0px; padding-left:0.3em;padding-right:0.3em;}
.tagglyTagging .button:hover, .hidebutton:hover { background:#eee; color:#888; }
.selected .tagglyTagging .button { display:inline; }
.tagglyTagging .hidebutton { color:white; } /* has to be there so it takes up space. tweak if you're not using a white tiddler bg */
.selected .tagglyTagging .hidebutton { color:#aaa }
.tagglyLabel { color:#aaa; font-size:90%; }
.tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }
.tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}
.tagglyTagging ul ul li {margin-left:0.5em; }
.editLabel { font-size:90%; padding-top:0.5em; }
/* TAB COLOR FIX */
.tabUnselected {color:[[ColorPalette::PrimaryDark]];}
/* GIFFMEX TWEAKS TO STYLESHEETPRINT (so that nothing but tiddler title and text are printed) */
@media print {#mainMenu {display: none ! important;}}
@media print {#topMenu {display: none ! important;}}
@media print {#sidebar {display: none ! important;}}
@media print {#messageArea {display: none ! important;}}
@media print {#toolbar {display: none ! important;}}
@media print {.header {display: none ! important;}}
@media print {.tiddler .subtitle {display: none ! important;}}
@media print {.tiddler .toolbar {display; none ! important; }}
@media print {.tiddler .tagging {display; none ! important; }}
@media print {.tiddler .tagged {display; none ! important; }}
@media print {#displayArea {margin: 1em 1em 0em 1em;}}
@media print {.pageBreak {page-break-before: always;}}
/*}}}*/
!!!StyleSheetTiddlersBar
#tiddlersBar .button {border:1px; color:#000;}
#tiddlersBar .tab {white-space:nowrap;}
#tiddlersBar {padding : 0.65em 0.5em 0.0em 1.0em;margin-left:0em;margin-right:0em}
#tiddlersBar {margin-bottom:0px;}
.tabSelected .button:hover {font-size:0.95em;font-weight:bold;color: #f00;background: #fff;padding : 0px 0px 0px 2px;}
.tabUnselected .button:hover {font-size:0.95em;color: #f00;background: #fff; padding : 0px 0px 0px 2px;}
.tabUnselected .button {font-size:0.95em;font-weight:bold;color: #008; padding : 0px 0px 0px 2px;}
.tabSelected .button {font-size:0.95em;font-weight:bold;color: #008;padding : 0px 0px 0px 2px;}
.tabUnselected {
background:url("http://img261.imageshack.us/img261/8603/navbargrayhw1.png") repeat-x top left;top left;
background-color:#eee;
border:0px #eee solid; border-bottom:0px;font-size:0.95em; }
.tabSelected {
background:url("http://img505.imageshack.us/img505/489/navbarredlt5.gif") repeat-x top left;top left;
background-color:#fcb;
color: #a00;border: 0px #c06 solid;border-bottom:0px; font-size:0.95em;}
.tabUnselected .tabButton {font-weight:bold;font-size:0.75em;color:#333;background:transparent; padding : 0px 2px 0px 2px; margin: 0 0 0 1px;}
.tabSelected .tabButton {font-weight:bold;font-size:0.75em;color:#000;background:transparent;padding : 0px 2px 0px 2px; margin: 0 0 0 1px;}
.tabSelected .tabButton:hover {font-weight:bold;color: #f00;background: #fff;}
.tabUnselected .tabButton:hover {font-weight:bold;color: #f00;background: #fff;}
.tiddler, .tabContents {border-top:0px #fa0 solid;margin-left:0.5em;margin-right:0.5em;}
#tiddlersBar .tab {-moz-border-radius : 0.4em 0.4em 0 0;}
#tiddlersBar {background:#abf;line-height: 1.45em;}
#tiddlersBar {background: url("http://img168.imageshack.us/img168/1254/leftbackdo6.gif"); background-repeat: repeat;line-height: 1.45em;}
|>|bgcolor(#8af):@@color(#000080):''3 tiddlers found matching /{{{siteur}}}/''@@|bgcolor(#8af): @@color(#A00000): SearchHelp@@ |
|>|>|bgcolor(#E3FFE3):<<search>> <<option chkSearchTitles>> Titles <<option chkSearchText>> Text <<option chkSearchTags>>Tags <<option chkHoldSearches>> Hold |
|bgcolor(#8af): |bgcolor(#8af): @@color(#000080):sort by: ''Titles''@@ |bgcolor(#8af): @@color(#000080): ''Size'' (bytes)@@ |bgcolor(#8af): @@color(#000080): ''Tags''@@ |h
| 1|[[ImportedTiddlers]]| 4778|@@@@|
| 2|[[SiteUrl]]| 37|@@excludeLists@@|
| 3|[[TspotSetupPlugin]]| 4338|@@systemConfig@@|
|sortable|k
<<calendar thismonth>><<forEachTiddler where 'tiddler.tags.contains("Calendar")>><<newTiddler title: 'New calendar year - replace XXXX below with the year you wish to view' text:{{store.getTiddlerText("CalendarYearSliderFrame")}} tag: 'Calendar' label:'Add new calendar year'>>
----
[[Add appointments]]
[[This week's appointments]]
[[All appointments]] (365 days}
<<forEachTiddler
where
'tiddler.tags.contains("contactgroup")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
[[All phone#s]]
[[All e-mails]]
----
<<forEachTiddler where 'tiddler.tags.contains("contact")'>>
{{centeredmenu{<<newTiddler title: 'Enter the name for your new contact group here' tag: 'contactgroup' label: 'New contact group ' text:{{store.getTiddlerText("ContactGroupSliderFrame")}}>>}}}{{centeredmenu{<<newTiddler title:'Name your new contact and click done to add data' label:"| New contact" text:{{"<<formTiddler NewContactTemplate\>\>"}} tag:"Contact">>}}}
<<tabs txtMenuMenu
"Contact groups" "Contact groups" TabContactGroups
"Contacts" "Contacts" TabContacts>>
<<tabs ""
"Help" "Help" TabHelp
"IFrames" "IFrames" TabIFrames
"GTD" "GTD" TabGTD
>>
[[What is GTD?]]
[[1. Collect your tasks]]
{{indent{[[Inbox]]
[[2. Process your tasks]]
[[3. Organize]]
[[4. Conduct a weekly review]]
[[5. Do your tasks]]
<<forEachTiddler
where
'tiddler.tags.contains("goal")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
[[Welcome]]
[[More info on TiddlyWiki]]
[[The TiddlyDu3 layout]]
[[Goals, projects, and tasks]]
[[Statuses and tasktypes]]
[[Contact groups and contacts]]
[[My Info]]
[[IFrames]]
[[Removing unwanted features]]
<<newTiddler title: 'New IFrame - replace XXXX below with the website you wish to access' text: '<html><div align="center"><iframe src="http://XXXX" frameborder="0" width="100%" height="600"></iframe></div></html>' tag: 'iframe' label:'New IFrame'>>
<<forEachTiddler where 'tiddler.tags.contains("iframe")>>
<<newTiddler title: 'New piece of info' tag: 'info' label:'New piece of info'>>
<<forEachTiddler where 'tiddler.tags.contains("info")'>>
<<forEachTiddler
where
'tiddler.tags.contains("project")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
[[Current]]
[[Waiting]]
[[Someday/Maybe]]
[[Reporting]]
----
<<forEachTiddler where 'tiddler.tags.contains("Tasktype")' sortBy 'tiddler.title'>>
<<forEachTiddler where 'tiddler.tags.contains("task")'>>
{{centeredmenu{<<newTiddler title: 'Enter the name for your new goal here' tag: 'goal' label: 'New goal |' text: {{store.getTiddlerText("GoalSliderFrame")}}>>}}}{{centeredmenu{<<newTiddler title: 'Enter the name for your new project here' tag: 'project' label: ' New project |' text:{{store.getTiddlerText("ProjectSliderFrame")}}>>}}}{{centeredmenu{<<newTiddler title: 'Enter the name for your new task here' tag: 'task' label: ' New task' text:{{store.getTiddlerText("TaskSliderFrame")}}>>}}}
<<tabs txtMenuMenu
"Goals" "Goals" TabGoals
"Projects" "Projects" TabProjects
"Tasks" "Tasks" TabTasks
"Task types" "Task types" TabTaskTypes>>
/***
|''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
// %/
#sidebarTabs .tabContents {
max-height: 35em; /* not IE6-compatible */
overflow: auto;
width: 90.5%;
}
#sidebarTabs .tabContents .tabContents {
max-height: 30em !important; /* not IE6-compatible */
}
#sidebarTabs .tabSelected {
background:url("http://img505.imageshack.us/img505/489/navbarredlt5.gif") repeat-x top left;top left;
background-color:#fcb;
font-size:0.95em;
font-weight:bold;
color:#a00;
text-decoration:none;
border: 0px solid #999;
}
#sidebarTabs .tabUnselected {
background:url("http://img261.imageshack.us/img261/8603/navbargrayhw1.png") repeat-x top left;top left;
background-color:#eee;
font-size:0.95em;
font-weight:bold;
color:#008;
text-decoration:none;
border: 0px solid #999;
}
#mainMenu a {text-decoration:none;}
#mainMenu ul {list-style-type:none;}
#mainMenu {padding: 0.2em 0.2em 0.2em 0.35em;}
#mainMenu ul {list-style-type:none;}
#mainMenu .tabUnselected {color:#008;}
#mainMenu .tabContents {width:98%;margin-left:0.25em;}
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.''
!!!!!Documentation
>see [[TaggedTemplateTweakInfo]]
!!!!!Revisions
<<<
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.
| please see [[TaggedTemplateTweakInfo]] for previous revision details |
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.taggedTemplate= {major: 1, minor: 1, revision: 0, date: new Date(2007,6,23)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
// get default template from core
var template=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
// if the tiddler to be rendered doesn't exist yet, just return core result
var tiddler=store.getTiddler(title); if (!tiddler) return template;
// look for template whose prefix matches a tag on this tiddler
for (t=0; t<tiddler.tags.length; t++) {
var tag=tiddler.tags[t];
if (store.tiddlerExists(tag+template)) { template=tag+template; break; }
// try capitalized tag (to match WikiWord template titles)
var cap=tag.substr(0,1).toUpperCase()+tag.substr(1);
if (store.tiddlerExists(cap+template)) { template=cap+template; break; }
}
return template;
}
//}}}
/***
|''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:#ccc; 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]]";
//}}}
/***
|Name:|TagglyTaggingPlugin|
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 6100 $)|
|Date:|$Date: 2008-07-27 01:42:07 +1000 (Sun, 27 Jul 2008) $|
|Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{
merge(String.prototype,{
parseTagExpr: function(debug) {
if (this.trim() == "")
return "(true)";
var anyLogicOp = /(!|&&|\|\||\(|\))/g;
var singleLogicOp = /^(!|&&|\|\||\(|\))$/;
var spaced = this.
// because square brackets in templates are no good
// this means you can use [(With Spaces)] instead of [[With Spaces]]
replace(/\[\(/g," [[").
replace(/\)\]/g,"]] ").
// space things out so we can use readBracketedList. tricky eh?
replace(anyLogicOp," $1 ");
var expr = "";
var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!
for (var i=0;i<tokens.length;i++)
if (tokens[i].match(singleLogicOp))
expr += tokens[i];
else
expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think
if (debug)
alert(expr);
return '('+expr+')';
}
});
merge(TiddlyWiki.prototype,{
getTiddlersByTagExpr: function(tagExpr,sortField) {
var result = [];
var expr = tagExpr.parseTagExpr();
store.forEachTiddler(function(title,tiddler) {
if (eval(expr))
result.push(tiddler);
});
if(!sortField)
sortField = "title";
result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
return result;
}
});
config.taggly = {
// for translations
lingo: {
labels: {
asc: "\u2191", // down arrow
desc: "\u2193", // up arrow
title: "title",
modified: "modified",
created: "created",
show: "+",
hide: "-",
normal: "normal",
group: "group",
commas: "commas",
sitemap: "sitemap",
numCols: "cols\u00b1", // plus minus sign
label: "Tagged as '%0':",
exprLabel: "Matching tag expression '%0':",
excerpts: "excerpts",
descr: "descr",
slices: "slices",
contents: "contents",
sliders: "sliders",
noexcerpts: "title only",
noneFound: "(none)"
},
tooltips: {
title: "Click to sort by title",
modified: "Click to sort by modified date",
created: "Click to sort by created date",
show: "Click to show tagging list",
hide: "Click to hide tagging list",
normal: "Click to show a normal ungrouped list",
group: "Click to show list grouped by tag",
sitemap: "Click to show a sitemap style list",
commas: "Click to show a comma separated list",
numCols: "Click to change number of columns",
excerpts: "Click to show excerpts",
descr: "Click to show the description slice",
slices: "Click to show all slices",
contents: "Click to show entire tiddler contents",
sliders: "Click to show tiddler contents in sliders",
noexcerpts: "Click to show entire title only"
},
tooDeepMessage: "* //sitemap too deep...//"
},
config: {
showTaggingCounts: true,
listOpts: {
// the first one will be the default
sortBy: ["title","modified","created"],
sortOrder: ["asc","desc"],
hideState: ["show","hide"],
listMode: ["normal","group","sitemap","commas"],
numCols: ["1","2","3","4","5","6"],
excerpts: ["noexcerpts","excerpts","descr","slices","contents","sliders"]
},
valuePrefix: "taggly.",
excludeTags: ["excludeLists","excludeTagging"],
excerptSize: 50,
excerptMarker: "/%"+"%/",
siteMapDepthLimit: 25
},
getTagglyOpt: function(title,opt) {
var val = store.getValue(title,this.config.valuePrefix+opt);
return val ? val : this.config.listOpts[opt][0];
},
setTagglyOpt: function(title,opt,value) {
if (!store.tiddlerExists(title))
// create it silently
store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");
// if value is default then remove it to save space
return store.setValue(title,
this.config.valuePrefix+opt,
value == this.config.listOpts[opt][0] ? null : value);
},
getNextValue: function(title,opt) {
var current = this.getTagglyOpt(title,opt);
var pos = this.config.listOpts[opt].indexOf(current);
// a little usability enhancement. actually it doesn't work right for grouped or sitemap
var limit = (opt == "numCols" ? store.getTiddlersByTagExpr(title).length : this.config.listOpts[opt].length);
var newPos = (pos + 1) % limit;
return this.config.listOpts[opt][newPos];
},
toggleTagglyOpt: function(title,opt) {
var newVal = this.getNextValue(title,opt);
this.setTagglyOpt(title,opt,newVal);
},
createListControl: function(place,title,type) {
var lingo = config.taggly.lingo;
var label;
var tooltip;
var onclick;
if ((type == "title" || type == "modified" || type == "created")) {
// "special" controls. a little tricky. derived from sortOrder and sortBy
label = lingo.labels[type];
tooltip = lingo.tooltips[type];
if (this.getTagglyOpt(title,"sortBy") == type) {
label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
onclick = function() {
config.taggly.toggleTagglyOpt(title,"sortOrder");
return false;
}
}
else {
onclick = function() {
config.taggly.setTagglyOpt(title,"sortBy",type);
config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
return false;
}
}
}
else {
// "regular" controls, nice and simple
label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
onclick = function() {
config.taggly.toggleTagglyOpt(title,type);
return false;
}
}
// hide button because commas don't have columns
if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
},
makeColumns: function(orig,numCols) {
var listSize = orig.length;
var colSize = listSize/numCols;
var remainder = listSize % numCols;
var upperColsize = colSize;
var lowerColsize = colSize;
if (colSize != Math.floor(colSize)) {
// it's not an exact fit so..
upperColsize = Math.floor(colSize) + 1;
lowerColsize = Math.floor(colSize);
}
var output = [];
var c = 0;
for (var j=0;j<numCols;j++) {
var singleCol = [];
var thisSize = j < remainder ? upperColsize : lowerColsize;
for (var i=0;i<thisSize;i++)
singleCol.push(orig[c++]);
output.push(singleCol);
}
return output;
},
drawTable: function(place,columns,theClass) {
var newTable = createTiddlyElement(place,"table",null,theClass);
var newTbody = createTiddlyElement(newTable,"tbody");
var newTr = createTiddlyElement(newTbody,"tr");
for (var j=0;j<columns.length;j++) {
var colOutput = "";
for (var i=0;i<columns[j].length;i++)
colOutput += columns[j][i];
var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
wikify(colOutput,newTd);
}
return newTable;
},
createTagglyList: function(place,title,isTagExpr) {
switch(this.getTagglyOpt(title,"listMode")) {
case "group": return this.createTagglyListGrouped(place,title,isTagExpr); break;
case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;
}
},
getTaggingCount: function(title,isTagExpr) {
// thanks to Doug Edmunds
if (this.config.showTaggingCounts) {
var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
if (tagCount > 0)
return " ("+tagCount+")";
}
return "";
},
getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);
},
getExcerpt: function(inTiddlerTitle,title,indent) {
if (!indent)
indent = 1;
var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
var t = store.getTiddler(title);
if (t && displayMode == "excerpts") {
var text = t.text.replace(/\n/," ");
var marker = text.indexOf(this.config.excerptMarker);
if (marker != -1) {
return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
}
else if (text.length < this.config.excerptSize) {
return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
}
else {
return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
}
}
else if (t && displayMode == "contents") {
return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
}
else if (t && displayMode == "sliders") {
return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
}
else if (t && displayMode == "descr") {
var descr = store.getTiddlerSlice(title,'Description');
return descr ? " {{excerpt{" + descr + "}}}" : "";
}
else if (t && displayMode == "slices") {
var result = "";
var slices = store.calcAllSlices(title);
for (var s in slices)
result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
return result ? "\n{{excerpt excerptIndent{\n" + result + "}}}" : "";
}
return "";
},
notHidden: function(t,inTiddler) {
if (typeof t == "string")
t = store.getTiddler(t);
return (!t || !t.tags.containsAny(this.config.excludeTags) ||
(inTiddler && this.config.excludeTags.contains(inTiddler)));
},
// this is for normal and commas mode
createTagglyListNormal: function(place,title,useCommas,isTagExpr) {
var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);
if (this.getTagglyOpt(title,"sortOrder") == "desc")
list = list.reverse();
var output = [];
var first = true;
for (var i=0;i<list.length;i++) {
if (this.notHidden(list[i],title)) {
var countString = this.getTaggingCount(list[i].title);
var excerpt = this.getExcerpt(title,list[i].title);
if (useCommas)
output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
else
output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");
first = false;
}
}
return this.drawTable(place,
this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
useCommas ? "commas" : "normal");
},
// this is for the "grouped" mode
createTagglyListGrouped: function(place,title,isTagExpr) {
var sortBy = this.getTagglyOpt(title,"sortBy");
var sortOrder = this.getTagglyOpt(title,"sortOrder");
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list = list.reverse();
var leftOvers = []
for (var i=0;i<list.length;i++)
leftOvers.push(list[i].title);
var allTagsHolder = {};
for (var i=0;i<list.length;i++) {
for (var j=0;j<list[i].tags.length;j++) {
if (list[i].tags[j] != title) { // not this tiddler
if (this.notHidden(list[i].tags[j],title)) {
if (!allTagsHolder[list[i].tags[j]])
allTagsHolder[list[i].tags[j]] = "";
if (this.notHidden(list[i],title)) {
allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";
leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers
}
}
}
}
}
var allTags = [];
for (var t in allTagsHolder)
allTags.push(t);
var sortHelper = function(a,b) {
if (a == b) return 0;
if (a < b) return -1;
return 1;
};
allTags.sort(function(a,b) {
var tidA = store.getTiddler(a);
var tidB = store.getTiddler(b);
if (sortBy == "title") return sortHelper(a,b);
else if (!tidA && !tidB) return 0;
else if (!tidA) return -1;
else if (!tidB) return +1;
else return sortHelper(tidA[sortBy],tidB[sortBy]);
});
var leftOverOutput = "";
for (var i=0;i<leftOvers.length;i++)
if (this.notHidden(leftOvers[i],title))
leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";
var output = [];
if (sortOrder == "desc")
allTags.reverse();
else if (leftOverOutput != "")
// leftovers first...
output.push(leftOverOutput);
for (var i=0;i<allTags.length;i++)
if (allTagsHolder[allTags[i]] != "")
output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);
if (sortOrder == "desc" && leftOverOutput != "")
// leftovers last...
output.push(leftOverOutput);
return this.drawTable(place,
this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
"grouped");
},
// used to build site map
treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {
var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);
if (sortOrder == "desc")
list.reverse();
var indent = "";
for (var j=0;j<depth;j++)
indent += "*"
var childOutput = "";
if (depth > this.config.siteMapDepthLimit)
childOutput += indent + this.lingo.tooDeepMessage;
else
for (var i=0;i<list.length;i++)
if (list[i].title != title)
if (this.notHidden(list[i].title,this.config.inTiddler))
childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);
if (depth == 0)
return childOutput;
else
return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;
},
// this if for the site map mode
createTagglyListSiteMap: function(place,title,isTagExpr) {
this.config.inTiddler = title; // nasty. should pass it in to traverse probably
var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
return this.drawTable(place,
this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
"sitemap"
);
},
macros: {
tagglyTagging: {
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var parsedParams = paramString.parseParams("tag",null,true);
var refreshContainer = createTiddlyElement(place,"div");
// do some refresh magic to make it keep the list fresh - thanks Saq
refreshContainer.setAttribute("refresh","macro");
refreshContainer.setAttribute("macroName",macroName);
var tag = getParam(parsedParams,"tag");
var expr = getParam(parsedParams,"expr");
if (expr) {
refreshContainer.setAttribute("isTagExpr","true");
refreshContainer.setAttribute("title",expr);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("isTagExpr","false");
if (tag) {
refreshContainer.setAttribute("title",tag);
refreshContainer.setAttribute("showEmpty","true");
}
else {
refreshContainer.setAttribute("title",tiddler.title);
refreshContainer.setAttribute("showEmpty","false");
}
}
this.refresh(refreshContainer);
},
refresh: function(place) {
var title = place.getAttribute("title");
var isTagExpr = place.getAttribute("isTagExpr") == "true";
var showEmpty = place.getAttribute("showEmpty") == "true";
removeChildren(place);
addClass(place,"tagglyTagging");
var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
if (countFound > 0 || showEmpty) {
var lingo = config.taggly.lingo;
config.taggly.createListControl(place,title,"hideState");
if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
createTiddlyElement(place,"span",null,"tagglyLabel",
isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
config.taggly.createListControl(place,title,"title");
config.taggly.createListControl(place,title,"modified");
config.taggly.createListControl(place,title,"created");
config.taggly.createListControl(place,title,"listMode");
config.taggly.createListControl(place,title,"excerpts");
config.taggly.createListControl(place,title,"numCols");
config.taggly.createTagglyList(place,title,isTagExpr);
if (countFound == 0 && showEmpty)
createTiddlyElement(place,"div",null,"tagglyNoneFound",lingo.labels.noneFound);
}
}
}
}
},
// todo fix these up a bit
styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
" margin-top:0px; padding-top:0.5em; padding-left:2em;",
" margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
" color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
" border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active {",
" border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
" margin-bottom:0.5em; }",
".tagglyTagging .indent1 { margin-left:3em; }",
".tagglyTagging .indent2 { margin-left:4em; }",
".tagglyTagging .indent3 { margin-left:5em; }",
".tagglyTagging .indent4 { margin-left:6em; }",
".tagglyTagging .indent5 { margin-left:7em; }",
".tagglyTagging .indent6 { margin-left:8em; }",
".tagglyTagging .indent7 { margin-left:9em; }",
".tagglyTagging .indent8 { margin-left:10em; }",
".tagglyTagging .indent9 { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",
"/*}}}*/",
""].join("\n"),
init: function() {
merge(config.macros,this.macros);
config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
store.addNotification("TagglyTaggingStyles",refreshStyles);
}
};
config.taggly.init();
//}}}
/***
InlineSlidersPlugin
By Saq Imtiaz
http://tw.lewcid.org/sandbox/#InlineSlidersPlugin
// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed
***/
//{{{
config.formatters.unshift( {
name: "inlinesliders",
// match: "\\+\\+\\+\\+|\\<slider",
match: "\\<slider",
// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
handler: function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
wikify(lookaheadMatch[3],panel);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
},
onClickSlider : function(e) {
if(!e) var e = window.event;
var n = this.nextSibling;
n.style.display = (n.style.display=="none") ? "block" : "none";
return false;
}
});
//}}}
<<siteMap [[Enter the name for your new task here, too]] . sliders>>
|bgcolor(#eeeeee):@@white-space: nowrap;<html><span style="padding-right:0.15em;" macro='monkeyTagger project'></span></html>@@|//Important:// select the ''project'' that this task belongs to.|
|bgcolor(#eeeeee):@@white-space: nowrap;<html><span style="padding-right:0.15em;" macro='monkeyTagger status'></span> </html>@@|Select each and every ''status'' that applies. Reporting sends it to your list of things to report to your superiors. Delete the task if it is done and no reporting is needed.|
|bgcolor(#eeeeee):@@white-space: nowrap;<html><span style="padding-right:0.15em;" macro='monkeyTagger Tasktype'></span></html>@@|If desired, select the ''task-type'' for this task.|
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span style="padding-right:0em;" macro='tagger'></span></div>
<div class='title' macro='view title'></div>
<span macro='formTiddler TaskTemplate'></span>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<<formTiddler NewContactTemplate>><data>{"firstname":"Dave","lastname":"Gifford","country":"Mexico"}</data>
<<siteMap [[Test contact group]] . sliders>>
<<siteMap [[Test goal]] . sliders>>
<<siteMap [[Test project]] . sliders>>
<<siteMap [[Test task]] . sliders>>
Just a quick tour of the ~TiddlyDu3 layout:
!Screen layout
*At the top you will find a ''topmenu'' from which you can search this file, and expand/collapse the left and right menus to adjust your monitor real estate.
*In the middle is the ''viewing area'', where notes appear. These notes are called 'tiddlers.' Each goal, task, contact, etc that you create will be its own tiddler. Tiddlers stay open until you close them.
*Between the topmenu and the viewing area is the ''Tiddlersbar''. This area contains the tabs of all open tiddlers. To close open tiddlers, click on 'close others' in the toolbar of the open tiddler, or 'Close all' in the topmenu.
*In the ''left-hand menu'' you will find tabs with indexes of your tasks, contacts, information and more. Some of these indexes are straightforward lists. Other indexes are automatically generated and updated as you create tiddlers and add them to categories using a simple tagging process.
*In the ''right-hand menu'' you will find standard ~TiddlyWiki controls, as well as more comprehensive indexes of the contents of this file.
!Tiddler layout
*In ''view mode'', a tiddler has a toolbar, a title, and an area for the tiddler's text or content. From the toolbar you can close the other open tiddlers, and close, edit or delete the present tiddler. In certain tiddlers you can create other tiddlers - e.g., from within a goal tiddler, you can create new project and task tiddlers that are part of that goal. The new tiddlers get added to the goal in the Goal tab.
*In ''edit mode'', a tiddler has a toolbar, a title, a title editing area, a formatting toolbar, a tag editing area, and a text editing area. Use the editing areas to modify the title, tags and text of your tiddler. Use the formatting toolbars to format selected text in the text editing area.
----
{{appta twocolumns{
<<schedule view:agenda hourFrom:8 span:13 shadow:on duration:9>>
}}}
/***
|''Name:''|TiddlersBarPluginMG|
|''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|
!Modification
2008.09.06 - Morris Gray (Added http://tw.lewcid.org/#OpenTopPlugin code to this plugin to overcome jumping to the top when invoking any popup. Deleted the offending code)
!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 : "do nothing";
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"));
}
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>");
//}}}
<<newJournal "YYYY.0MM.0DD at 0hh:0mm:0ss" "Atopic" "ChangeNotes" label:ChangeNote >> | <<openAll ChangeNotes closeAllFirst>>
----
{{bluey{TiddlyDu3}}}@@padding-left:0.5em;font-size:7pt;<<newTiddler title: 'Enter the name for your new sub topic here' tag: 'TiddlyDu3' 'Atopic' label: 'subTopic | ' text: {{store.getTiddlerText("SliderFrame")}} label: 'New Master Topic'>><script label="refresh">
story.forEachTiddler(function(t,e)
{story.refreshTiddler(t,null,true)});
refreshDisplay();
return false;
</script>@@
<<forEachTiddler
where
'tiddler.tags.contains("TiddlyDu3")'
script
'
function getFirstLine(s) {
var m = s.match(/\s*(.*)/);
return m != null && m.length >= 1 ? m[1] : "";
}
'
write
'getFirstLine(tiddler.text)'
>>
<html><div align="center"><iframe src="http://www.giffmex.org/tw/tiddlywikicentral.html" frameborder="0" width="100%" height="600"></iframe></div></html>
/%
|Name|ToggleLeftSidebar|
|Source|http://www.TiddlyTools.com/#ToggleLeftSidebar|
|Version|2.0.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|show/hide left sidebar (MainMenu)|
Usage: <<tiddler ToggleLeftSidebar with: "label">>
Config settings:
config.options.chkShowLeftSidebar (true)
config.options.txtToggleLeftSideBarLabelShow (►)
config.options.txtToggleLeftSideBarLabelHide (◄)
%/<script label="$1" title="show/hide MainMenu content">
var co=config.options;
if (co.chkShowLeftSidebar=='undefined') co.chkShowLeftSidebar=true;
co.chkShowLeftSidebar=!co.chkShowLeftSidebar;
var mm=document.getElementById('mainMenu'); if (!mm) return;
mm.style.display=co.chkShowLeftSidebar?'block':'none';
document.getElementById('displayArea').style.marginLeft=co.chkShowLeftSidebar?'':'1em';
saveOptionCookie('chkShowLeftSidebar');
var labelShow=co.txtToggleLeftSideBarLabelShow||'►';
var labelHide=co.txtToggleLeftSideBarLabelHide||'◄';
if (typeof(place)!='undefined' && '$1'=='$'+'1') {
place.innerHTML=co.chkShowLeftSidebar?labelHide:labelShow;
place.title=(co.chkShowLeftSidebar?'hide':'show')+' left sidebar';
}
var sm=document.getElementById('storyMenu'); if (sm) config.refreshers.content(sm);
</script><script>
var co=config.options;
if (co.chkShowLeftSidebar=='undefined') co.chkShowLeftSidebar=true;
var mm=document.getElementById('mainMenu'); if (!mm) return;
mm.style.display=co.chkShowLeftSidebar?'block':'none';
document.getElementById('displayArea').style.marginLeft=co.chkShowLeftSidebar?'':'1em';
if ('$1'=='$'+'1') {
var labelShow=co.txtToggleLeftSideBarLabelShow||'►';
var labelHide=co.txtToggleLeftSideBarLabelHide||'◄';
place.lastChild.innerHTML=co.chkShowLeftSidebar?labelHide:labelShow;
place.lastChild.title=(co.chkShowLeftSidebar?'hide':'show')+' left sidebar';
}
</script>
/%
|Name|ToggleRightSidebar|
|Source|http://www.TiddlyTools.com/#ToggleRightSidebar|
|Version|2.0.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|show/hide right sidebar (MainMenu)|
Usage: <<tiddler ToggleRightSidebar with: "label">>
Config settings:
config.options.chkShowRightSidebar (false)
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||(config.browser.isSafari?'◀':'◄');
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||(config.browser.isSafari?'◀':'◄');
var labelHide=co.txtToggleRightSideBarLabelHide||'►';
place.lastChild.innerHTML=co.chkShowRightSidebar?labelHide:labelShow;
place.lastChild.title=(co.chkShowRightSidebar?'hide':'show')+' right sidebar';
}
</script>
/***
|Name:|ToggleTagPlugin|
|Description:|Makes a checkbox which toggles a tag in a tiddler|
|Version:|3.1.0 ($Rev: 4907 $)|
|Date:|$Date: 2008-05-13 03:15:46 +1000 (Tue, 13 May 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ToggleTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}
* TagName - the tag to be toggled, default value "checked"
* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler
* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'
(If a parameter is '.' then the default will be used)
* TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date
!!Examples
|Code|Description|Example|h
|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|
|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|
|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|
|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|
|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|
!!Notes
* If TiddlerName doesn't exist it will be silently created
* Set label to '-' to specify no label
* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2
!!Known issues
* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing
* Should convert to use named params
***/
//{{{
if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false;
merge(config.macros,{
toggleTag: {
createIfRequired: true,
shortLabel: "[[%0]]",
longLabel: "[[%0]] [[%1]]",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var tiddlerTitle = tiddler ? tiddler.title : '';
var tag = (params[0] && params[0] != '.') ? params[0] : "checked";
var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle;
var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel);
var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;
var touchMod = (params[3] && params[3] != '.') ? params[3] : "";
label = (label == '-' ? '' : label); // dash means no label
var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title));
var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {
if (!store.tiddlerExists(title)) {
if (config.macros.toggleTag.createIfRequired) {
var content = store.getTiddlerText(title); // just in case it's a shadow
store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);
}
else
return false;
}
if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler)
theTiddler.modified = new Date();
store.setTiddlerTag(title,this.checked,tag);
return true;
});
}
}
});
//}}}
|~ViewToolbar|newHere closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump|
|~EditToolbar|+saveTiddler saveCloseTiddler -cancelTiddler cancelCloseTiddler deleteTiddler|
<html><hide linebreaks><div id="slantedmenu" style="font-size:0.75em;"><ul><li> <a href="javascript:void(0)" onclick="story.closeAllTiddlers();story.displayTiddlers(null,store.getTiddlerText('DefaultTiddlers').readBracketedList())"
><span title="Close all tiddlers and open Welcome" style="cursor:pointer">''Home''</span></a></li>|<li><<tiddler Refresh>></li>|<li>[[New Master Topic|Creating A New Master Topic]]</li>|<li>{{nowrap{<<search>>}}}</li><li>[[?|Find]]</li><li><<tiddler ToggleRightSidebar with: "Sidebar»">></li></ul></div></html>
/***
!!!SlantedStyle /%==================================================%/
***/
{{{
http://img261.imageshack.us/img261/8603/navbargrayhw1.png
http://img520.imageshack.us/img520/8688/mainmenugray7ef.gif
background-image: url("http://img264.imageshack.us/img264/4134/headbackbgdc6.png");background-repeat: repeat-x top-left;
}}}
/*Credits: Dynamic Drive CSS Library */
/*URL: http://www.dynamicdrive.com/style/ */
{{{
#slantedmenu{
font-size: 90%;
position: fixed !important;
width: 100%;
z-index:1
}
}}}
#slantedmenu{
font-size: 90%;}
#slantedmenu:after{ /*Add margin between menu and rest of content in Firefox*/
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
#slantedmenu ul{
text-indent: 10px;
padding: 3px 0;
margin: 0;
background:url("http://img261.imageshack.us/img261/8603/navbargrayhw1.png") repeat-x top left;top left;
background-color: #000;
border-top: 0px solid #f6f;
border-bottom: 0px solid #f6f;
text-align: center; /*set value to "center" for example to center items*/
}
#slantedmenu ul li{
display: inline;
}
#slantedmenu ul li a{
font-weight: normal;
color: #00a;
padding: 3px 0;
padding-right: 5px;
padding-left: 5px;
margin: 0;
text-decoration: none;
background: transparent url() top right no-repeat;
}
#slantedmenu ul li a:hover{
color: #f00;
background:#fff;
}
{{centeredmenu{<<tiddler ToggleLeftSidebar with: "(Left menu)">>}}}{{centeredmenu{<<search>>}}}{{centeredmenu{<<closeAll>>}}}{{centeredmenu{<<tiddler ToggleRightSidebar with: "(Right sidebar)">>}}}
/***
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 = 'twtudu';
// 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")
});
//}}}
/***
|Name|TwHelpSearchPlugin|
|Source|http://twhelp.tiddlyspot.com/#TwHelpSearchPlugin|
|Documentation|http://twhelp.tiddlyspot.com/#TWHelpSearchDoc|
|Version|1.0.6|
|Author|Morris Gray|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.0 - 2.4|
|Type|plugin|
|Requires|[[SearchOptionsPlugin|http://www.TiddlyTools.com/#SearchOptionsPlugin]] [[TableSortingPlugin|http://tw.lewcid.org/#TableSortingPlugin]] (only for sorting option)|
|Overrides|SearchOptionsPlugin's search results|
|Description|Extends the search results from SearchOptionsPlugin to a sortable table showing title, size and tags.|
''Demo search:''
|>|>|>|<<search>> |
|>|>| look for in |>|>|>|
| <<option chkSearchTitles>> | <<option chkSearchText>> | <<option chkSearchTags>> | <<option chkHoldSearches>> |
| titles | text | tags | hold |
''A Plugin Tweak for:'' SearchOptionsPlugin
!!!!!Description
<<<
This plugin defines an alternative format for the SearchResults tiddler that is generated by the SearchOptionsPlugin . It presents the search results in tabular form numbering the rows; and showing the tiddler title, the size in bytes, and the tags. It is ready to be used with the [[TableSortingPlugin|http://tw.lewcid.org/#TableSortingPlugin]] (check versions) so any column can be sorted; such as size in ascending or descending order.
<<<
!!!!!Installation
<<<
Import (or copy/paste) the following tiddlers into your ~TiddlyWiki:
* http://twhelp.tiddlyspot.com/#TwHelpSearchPlugin
*SearchOptionsPlugin from http://www.tiddlytools.com/#SearchOptionsPlugin
* Get more documentation here [[TWHelpSearchDoc]] or here:
* http://twhelp.tiddlyspot.com/#TwHelpSearchDoc
<<<
!!!!!Revision History
<<<
''2008.09.14 [1.0.6]''
Cosmetic - Add header.
''2007.09.12 [1.0.6]''
Added overflow scroll to TWHelp-SearchResults for long titles or tags.
''2006.02.03 [1.0.5]''
Added facility for holding the results of multiple searches with tick box on dashboard.
''2006.02.02 [1.0.4]''
Added several options, cleaned up design.Planning one version basic and one with added options this is the added options version.
''2006.01.27 [1.0.3''
Added a column for the size of the text in each tiddler, this does not include the size of the title or tags. Added overall TW statistics button requires TiddlerStatsPlugin.
''2006.01.23 [1.0.2 ]''
''a)''Changed function reportSearchResults(text,matches) to window.reportSearchResults=function(text,matches)
''b)''Added a line so that Incremental Search is automatically disabled config.options.chkSearchIncremental=false; turn off key-by-key searching
''c)''Removed space inside parens. bgcolor(#fe8 )" to "bgcolor(#fe8)". This
is what was causing IE to 'crap out' halfway through drawing the table
headings.
''d)''Added {{{config.options.chkSearchList=true;}}}
''2006.01.20 [1.0.1]''
ELS: reportSearchResults() definition moved to this Plugin Tweak tiddler and removed extranous code
''2006.01.19 [1.0.0]''
This is an adaptation of Eric Shulman's SearchOptionsPlugin. Adapted by MorrisGray to provide search results in table form. All the necessary controls for refining the search is provided within the table including slide-down access to AdvancedOptions.
<<<
!!!!!Code
***/
//{{{
if (config.options.chkSinglePageMode==undefined) config.options.chkSinglePageMode=false;
if (config.options.chkRegExpSearch==undefined) config.options.chkRegExpSearch=true;
if (config.options.chkSearchTitles==undefined) config.options.chkSearchTitles=false;
if (config.options.chkSearchText==undefined) config.options.chkSearchText=true;
if (config.options.chkSearchTags==undefined) config.options.chkSearchTags=false;
if (config.options.chkSearchTitlesFirst==undefined) config.options.chkSearchTitlesFirst=true;
if (config.options.chkSearchList==undefined) config.options.chkSearchList=true;
if (config.options.chkSearchIncremental==undefined) config.options.chkSearchIncremental=false;
if (config.options.chkToggleLinks==true) config.options.chkToggleLinks=false;
if (config.options.chkHoldSearches==undefined) config.options.chkHoldSearches=false;
if (config.options.chkSortTags==undefined) config.options.chkSortTags=false;
config.options.chkToggleLinks=false;
config.options.chkSinglePageMode=false;
config.options.chkHoldSearches=false;
config.options.chkSearchIncremental=false;
config.options.chkHttpReadOnly = false;
config.options.chkRegExpSearch=true;
config.options.chkSearchList=true;
config.options.chkToggleLinks=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkHoldSearches>> Hold search results";
//}}}
//{{{
// Give the report a custom name
config.macros.search.reportTitle="TWHelp-SearchResults";
// Override default SearchOptionsPlugin formatting for SearchResults tiddler
window.reportSearchResults=function(text,matches)
{
var title=config.macros.search.reportTitle
config.macros.search.reportTitle;
var q = config.options.chkRegExpSearch ? "/" : "'";
if (!config.options.chkHoldSearches) body="";
body+="\n|>|bgcolor(#8af):@@color(#000080):''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''@@|bgcolor(#8af): @@color(#A00000): SearchHelp@@ "+"|"+"\n";
body+="|>|>|bgcolor(#E3FFE3):<<search>> <<option chkSearchTitles>> Titles <<option chkSearchText>> Text <<option chkSearchTags>>Tags <<option chkHoldSearches>> Hold |"+"\n";
body+="\n|bgcolor(#8af): |bgcolor(#8af): @@color(#000080):sort by: ''Titles''@@ |bgcolor(#8af): @@color(#000080): ''Size'' (bytes)@@ |bgcolor(#8af): @@color(#000080): ''Tags''@@ |h";
for(var t=0;t<matches.length;t++)
body+="\n"+"| "+(t+1)+"|[["+matches[t].title+"]]| "+matches[t].text.length+"|"+"@@"+matches[t].tags+"@@"+"|";
body+="\n|sortable|k";
body+="\n";
// create/update the tiddler
var tiddler=store.getTiddler(title); if (!tiddler) tiddler=new Tiddler();
tiddler.set(title,body,config.options.txtUserName,(new Date()),"excludeLists excludeSearch killbookmark");
store.addTiddler(tiddler); story.closeTiddler(title);
// render tiddler
var oldprompt=config.macros.search.label;
config.macros.search.label="search again"; // use alternate "search again" label
story.displayTiddler(null,title,1); // force refresh
config.macros.search.label=oldprompt; // restore standard search label
}
//}}}
{{textcenter{
@@padding-left:1.2em;+++[Clock UTC]...<html><hide linebreaks><td align="center"><embed src="http://www.worldtimeserver.com/clocks/wtsclock024.swf?color=008080&wtsid=UTC" width="100" height="100" wmode="transparent" type="application/x-shockwave-flash" /><br>@@font-size:8pt;color:#008080;[[World Time|WorldTime]]@@</td></html>+++}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 11/02/2009 01:36:14 | YourName | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 10:09:12 | YourName | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 10:52:05 | YourName | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 11:26:08 | MsgRay | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 11:35:48 | MsgRay | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 11:53:03 | MsgRay | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 12:06:21 | MsgRay | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 11/02/2009 12:14:19 | YourName | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . | ok |
| 13/02/2009 10:44:25 | YourName | [[twtudu.html|file:///K:/TWNotes/twtudu.html]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.tiddlyspot.com/index.html]] | . |
| 26/02/2009 21:31:45 | YourName | [[/|http://twtudu.tiddlyspot.com/]] | [[store.cgi|http://twtudu.tiddlyspot.com/store.cgi]] | . | [[index.html | http://twtudu.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");
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'><span style="padding-right:0em;" macro='tagger'></span></div>
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<<forEachTiddler where 'tiddler.tags.contains("Visit, meet with")' sortBy 'tiddler.title'>>
As you add the 'waiting' tag to your tasks, they will show up below. Use this list to keep track of tasks for which you are waiting for someone or something.
<<forEachTiddler where 'tiddler.tags.contains("Waiting")>>
Welcome to ~TiddlyDu3, a free, all-in-one, portable personal organizer using ~TiddlyWiki technology. This is one file (html) that you can download to your computer or USB drive, and then view and edit (offline) from any computer with a web browser. It is designed to help you quickly and easily organize your to-do list items, appointments, calendars, contacts, and the information you need to have on hand. Each task, contact, etc, is assigned its own 'notecard', called a tiddler. All the tiddlers are contained in this one file and are easy to organize and retrieve. Here's an idea of what you can do with ~TiddlyDu3:
*In the ''Tasks'' tab in the left menu, you can add your life goals, then fit projects within those goals, and tasks within those projects. These items all appear in automatically updated indexes when you click the refresh button on the upper right. For any task, can specify the type of task it is, and other aspects, such as priority, waiting, reporting. There are separate indexes for all of these. //NOTE: All editing features are hidden in this file, but will be visible when you download it to your computer.//
*In the ''Calendars'' tab, you can see this month's calendar, and access other month and year calendars. You can also schedule appointments for yourself that show up on the month calendars and in separate lists.
*In the ''Contacts'' tab, you can add new contacts and organize them by contact groups in automatically updated lists.
*In the ''Info'' tab, you can add bits of information that you want to have on hand at all times, such as passowrds and pin numbers, special instructions, and things you easily forget.
*In the ''Extras'' tab, you can quickly create ~IFrames (portals to other websites), find out how to use ~TiddlyDu3 with the Getting Things Done system, and get help using ~TiddlyDu3.
*From the ''topmenu'' you can search this file and close all open tiddlers. You can also hide or show the left and right menus to better manage your on-screen real estate.
*The ''tiddler tabs'' show what tiddlers you have open. Use 'Close all' in the topmenu to close all tiddlers, or 'close others' in the open tiddler's toolbar to close all other tabs.
To ''save this file to your computer'', just right-click on [[this link|tiddlydu3.html]], choose "save link as", and choose a name and location for your file. If you use any other browser than Firefox, you will need to [[click here|http://www.tiddlywiki.com/TiddlySaver.jar]], save the ~TiddlySaver file to the same folder// (~TiddlySaver is a Java applet that allows you to save changes in various browsers that don't support saving changes to local files)//. Finally, close this webpage and open your saved ~TiddlyDu3 file to begin using and editing it.
GTD is short for ''Getting Things Done'', a personal organization method created by David Allen. You can use ~TiddlyDu3 to organize most aspects of the GTD system. In the GTD tab we have listed the five basic steps of GTD with ideas for integrating ~TiddlyDu3 with this system.
!Links
[[David Allen's official site|http://www.davidco.com/]]
[[GTD on 43 folders|http://www.43folders.com/2004/09/08/getting-started-with-getting-things-done]]
[[Buy Getting Things Done on Amazon|http://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0142000280/ref=sr_1_1?ie=UTF8&s=books&qid=1234061429&sr=1-1]]
<html><center><embed src="http://www.clocklink.com/clocks/world001-blue.swf?TimeZone=GMT&" width="525" height="285" wmode="transparent" type="application/x-shockwave-flash"></center></html>
<<forEachTiddler where 'tiddler.tags.contains("Write")' sortBy 'tiddler.title'>>
config.tasks.viewTabs = {
text: "editA",
tooltip: "Edit a specific tiddler",
content: "|width:18em;<<tiddler EditATiddler>>|"
};
config.backstageTasks.splice(config.backstageTasks.indexOf("save")+0,0,"viewTabs");
//{{{
config.options.chkHttpReadOnly = false;
config.options.chkAutoSave = true;
config.options.chkSaveBackups = false;
config.options.chkAnimate = false;
config.options.chkShowRightSidebar = false;
config.options.chkShowLeftSidebar=true;
if (window.location.protocol!="file:") showBackstage=false;
config.options.chkSearchTitles=true;
config.options.chkSearchText=true;
config.options.chkSearchTags=true;
config.options.chkSearchFields=true;
config.options.chkSearchTitlesFirst=false;
config.options.chkSearchList=true;
config.options.chkSearchByDate=false;
config.options.chkSearchIncremental=true;
config.options.chkSearchShadows=false;
config.options.chkShowQuickEdit=true;
//}}}