Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
A minute about an event recorded as a journal entry using the ''new journal'' command.
|Name|~TiddlyTimeJournal|
| Description|A simple tool to help you keep a journal of where your time goes|
| Version|0.9 beta|
| Date|<<today>>|
| Source|http://ttj.wombatdiet.net|
| Author|Eats Wombats|
| Email|eatswombats (at) wombatdiet (dot) net|
| License|[img[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/images/public/somerights20][http://creativecommons.org/licenses/by-sa/3.0/]]|
~TiddlyTimeJournal is based upon ~TiddlyWiki <<version>>, written by Jeremy Ruston, ©2005 Osmosoft Limited, published under a BSD open source license. Redistribution and Use in source and binary forms, with or without Modification are granted, unless otherwise noted, subject to the terms and conditions of the license (click on the image above for details).
''Core:'' Tiddlywiki <<version>> http://www.tiddlywiki.com
''Plugins''
TaskTimerPlugin 1.3.0 by Eric Shulman
[[Clock2]] 1.06 by Simon Baird
BetterTimelineMacro 0.5b by Saq Imtiaz; requires DeprecatedFunctionsPlugin with TW 2.4.1
DeprecatedFunctionsPlugin
InstantTimestamp 1.0.4 by Simon Baird
LessBackupsPlugin 3.0.1 by Simon Baird
LinkToMeMacro by Simon Baird
SaveOnExitPlugin 2.0 by Eric Shulman
ForEachTiddlerPlugin 1.0.8 by Udo Borkowski
ForEachTiddlerMacro 1.0.8 by Udo Borkowski;
ToggleSideBarMacro 1.0 by Saq Imtiaz
''Customizations You May Wish To Make''
*To adjust the number of backups made when you save changes: click here: LessBackupsPlugin, and edit as required.
*Likewise, the date format for timestamps can be changed by editing the InstantTimestamp plugin. Date format information [[here|http://tiddlywiki.com/#DateFormatString]].
!Version History
0.9 beta 1; TW 2.4.1 {{ds{2008-08-18}}}
|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|
|2008-08-18|First|02:47:04|02:47:10|00:00:06|
/%tasktimer%/
I created TTJ because I couldn't find, quickly, a //simple, elegant and free// application to help me keep a time journal. At first, I wanted something that would run in Vista's taskbar, or, better, a Yahoo desktop or an Opera browser widget.
There are countless time recording and activity logging applications out there whose focus is on invoicing -- on the attribution of billable hours. Many are expensive. Some are large (e.g., [[TimeStation|http://www.timestation.dataflower.net]]). Most are old Windows applications of uncertain origin and security. A lot are simply unattractive for the price. There may be some freely available gems, but who can find them amidst the dross?
What if you are a student or someone whose time isn't billed? What if your concern is not ''billable hours'' but simply monitoring your ''focus'', managing your attention and being aware of, and hopefully minimising, the impact of interruptions of various kinds? What if you work on more than one kind of computer?
<html><font size=4><b>With TiddlyTimeJournal you can</b></font></html>
* Quickly and easily record time expended on various activities //and interruptions// with a minimum of keystrokes
* Rapidly record date & time stamped events and milestones in an event log
* Create date & time stamped notes instantly (click ''new journal'' on the right menu bar)
It runs on @@any@@ computer that runs Firefox. ~TiddlyTimeJournal uses a clock animation that is not compatible with Internet Explorer, but this doesn't affect the rest of its functionality.
Click here for some [[Tips]]. You're welcome to send me yours, especially if you find a better mousetrap.
/***
|Name|BetterTimelineMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#BetterTimelineMacro|
|Version|0.5 beta|
|Requires|~TW2.x|
!!!Description:
A replacement for the core timeline macro that offers more features:
*list tiddlers with only specfic tag
*exclude tiddlers with a particular tag
*limit entries to any number of days, for example one week
*specify a start date for the timeline, only tiddlers after that date will be listed.
!!!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.
Edit the ViewTemplate to add the fullscreen command to the toolbar.
(Ignore last instruction. Not needed. Depends on another Lewcid extension and this was not indicated -- EW)
!!!Syntax:
{{{<<timeline better:true>>}}}
''the param better:true enables the advanced features, without it you will get the old timeline behaviour.''
additonal params:
(use only the ones you want)
{{{<<timeline better:true onlyTag:Tag1 excludeTag:Tag2 sortBy:modified/created firstDay:YYYYMMDD maxDays:7 maxEntries:30>>}}}
Note: Use this to replace the contents of the ShadowTiddler TabTimeline -- EW
''explanation of syntax:''
onlyTag: only tiddlers with this tag will be listed. Default is to list all tiddlers.
excludeTag: tiddlers with this tag will not be listed.
sortBy: sort tiddlers by date modified or date created. Possible values are modified or created.
firstDay: useful for starting timeline from a specific date. Example: 20060701 for 1st of July, 2006
maxDays: limits timeline to include only tiddlers from the specified number of days. If you use a value of 7 for example, only tiddlers from the last 7 days will be listed.
maxEntries: limit the total number of entries in the timeline.
!!!History:
*28-07-06: ver 0.5 beta, first release
!!!Code
***/
//{{{
// Return the tiddlers as a sorted array
TiddlyWiki.prototype.getTiddlers = function(field,excludeTag,includeTag)
{
var results = [];
this.forEachTiddler(function(title,tiddler)
{
if(excludeTag == undefined || tiddler.tags.find(excludeTag) == null)
if(includeTag == undefined || tiddler.tags.find(includeTag)!=null)
results.push(tiddler);
});
if(field)
results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
return results;
}
//this function by Udo
function getParam(params, name, defaultValue)
{
if (!params)
return defaultValue;
var p = params[0][name];
return p ? p[0] : defaultValue;
}
window.old_timeline_handler= config.macros.timeline.handler;
config.macros.timeline.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var args = paramString.parseParams("list",null,true);
var betterMode = getParam(args, "better", "false");
if (betterMode == 'true')
{
var sortBy = getParam(args,"sortBy","modified");
var excludeTag = getParam(args,"excludeTag",undefined);
var includeTag = getParam(args,"onlyTag",undefined);
var tiddlers = store.getTiddlers(sortBy,excludeTag,includeTag);
var firstDayParam = getParam(args,"firstDay",undefined);
var firstDay = (firstDayParam!=undefined)? firstDayParam: "00010101";
var lastDay = "";
var field= sortBy;
var maxDaysParam = getParam(args,"maxDays",undefined);
var maxDays = (maxDaysParam!=undefined)? maxDaysParam*24*60*60*1000: (new Date()).getTime() ;
var maxEntries = getParam(args,"maxEntries",undefined);
var last = (maxEntries!=undefined) ? tiddlers.length-Math.min(tiddlers.length,parseInt(maxEntries)) : 0;
for(var t=tiddlers.length-1; t>=last; t--)
{
var tiddler = tiddlers[t];
var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
if ((theDay>=firstDay)&& (tiddler[field].getTime()> (new Date()).getTime() - maxDays))
{
if(theDay != lastDay)
{
var theDateList = document.createElement("ul");
place.appendChild(theDateList);
createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(this.dateFormat));
lastDay = theDay;
}
var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink",null);
theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
}
}
}
else
{
window.old_timeline_handler.apply(this,arguments);
}
}
//}}}
/***
| Name:|Clock2|
| Author:|Simon Baird|
| Description:|A skinnable, sizeable analog clock|
| Source:|http://tiddlyspot.com/mptw/#Clock2|
| Requires:|Firefox 1.5.x or maybe Safari|
| Version:|1.0.6|
| Date:|8-Jul-2008|
!!Note
* Does not work in IE or Opera due to lack of canvas support.
* If you make a nice skin send it to me and I will include it here.
*I'm not actively maintaining this plugin
* See also http://randomibis.com/coolclock/
!!Ideas
* Can we support IE with this? http://sourceforge.net/projects/excanvas
* Skin should specify order of drawing so things can be on top of other things
* Fix it so we can have filled and/or stroked elements
* Skin should allow any number of moving and static elements
* Make download and example for non-TW use
* Make floating draggable?
!!Examples
{{{
<<clock2 fancy>><<clock2 120>>
<<clock2 chunkySwiss>> <<clock2 60 chunkySwiss noSeconds>><<clock2 '{
outerBorder: { lineWidth: 60, radius:55, color: "#dd8877", alpha: 1 },
smallIndicator: { lineWidth: 4, startAt: 80, endAt: 95, color: "white", alpha: 1 },
largeIndicator: { lineWidth: 12, startAt: 77, endAt: 89, color: "#dd8877", alpha: 1 },
hourHand: { lineWidth: 15, startAt: -15, endAt: 50, color: "white", alpha: 1 },
minuteHand: { lineWidth: 10, startAt: 24, endAt: 200, color: "#771100", alpha: 0.6 },
secondHand: { lineWidth: 3, startAt: 22, endAt: 83, color: "green", alpha: 0 },
secondDecoration: { lineWidth: 1, startAt: 52, radius: 26, fillColor: "white", color: "red", alpha: 0.2 }
}'>>
}}}
<<clock2 fancy>><<clock2 120>>
<<clock2 chunkySwiss>> <<clock2 60 chunkySwiss noSeconds>><<clock2 '{
outerBorder: { lineWidth: 60, radius:55, color: "#dd8877", alpha: 1 },
smallIndicator: { lineWidth: 4, startAt: 80, endAt: 95, color: "white", alpha: 1 },
largeIndicator: { lineWidth: 12, startAt: 77, endAt: 89, color: "#dd8877", alpha: 1 },
hourHand: { lineWidth: 15, startAt: -15, endAt: 50, color: "white", alpha: 1 },
minuteHand: { lineWidth: 10, startAt: 24, endAt: 200, color: "#771100", alpha: 0.6 },
secondHand: { lineWidth: 3, startAt: 22, endAt: 83, color: "green", alpha: 0 },
secondDecoration: { lineWidth: 1, startAt: 52, radius: 26, fillColor: "white", color: "red", alpha: 0.2 }
}'>>
See also BigClock.
!!Code
***/
//{{{
window.CoolClock = function(canvasId,displayRadius,skinId,showSecondHand) {
return this.init(canvasId,displayRadius,skinId,showSecondHand);
}
CoolClock.config = {
clockTracker: {},
tickDelay: 1000,
longTickDelay: 15000,
defaultRadius: 85,
renderRadius: 100,
defaultSkin: "swissRail",
skins: {
// try making your own...
swissRail: {
outerBorder: { lineWidth: 1, radius:95, color: "black", alpha: 1 },
smallIndicator: { lineWidth: 2, startAt: 89, endAt: 93, color: "black", alpha: 1 },
largeIndicator: { lineWidth: 4, startAt: 80, endAt: 93, color: "black", alpha: 1 },
hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 },
minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 },
secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 },
secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 }
},
chunkySwiss: {
outerBorder: { lineWidth: 5, radius:97, color: "black", alpha: 1 },
smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 },
largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 },
hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 },
minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 },
secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 },
secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 }
},
fancy: {
outerBorder: { lineWidth: 5, radius:95, color: "green", alpha: 0.7 },
smallIndicator: { lineWidth: 1, startAt: 80, endAt: 93, color: "black", alpha: 0.4 },
largeIndicator: { lineWidth: 1, startAt: 30, endAt: 93, color: "black", alpha: 0.5 },
hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "blue", alpha: 0.7 },
minuteHand: { lineWidth: 7, startAt: -15, endAt: 92, color: "red", alpha: 0.7 },
secondHand: { lineWidth: 10, startAt: 80, endAt: 85, color: "blue", alpha: 0.3 },
secondDecoration: { lineWidth: 1, startAt: 30, radius: 50, fillColor: "blue", color: "red", alpha: 0.15 }
}
}
};
CoolClock.prototype = {
init: function(canvasId,displayRadius,skinId,showSecondHand) {
this.canvasId = canvasId;
this.displayRadius = displayRadius || CoolClock.config.defaultRadius;
this.skinId = skinId || CoolClock.config.defaultSkin;
this.showSecondHand = typeof showSecondHand == "boolean" ? showSecondHand : true;
this.tickDelay = CoolClock.config[ this.showSecondHand ? "tickDelay" : "longTickDelay"];
this.canvas = document.getElementById(canvasId);
this.canvas.setAttribute("width",this.displayRadius*2);
this.canvas.setAttribute("height",this.displayRadius*2);
this.renderRadius = CoolClock.config.renderRadius;
var scale = this.displayRadius / this.renderRadius;
this.ctx = this.canvas.getContext("2d");
this.ctx.scale(scale,scale);
CoolClock.config.clockTracker[canvasId] = this;
this.tick();
return this;
},
fullCircle: function(skin) {
this.fullCircleAt(this.renderRadius,this.renderRadius,skin);
},
fullCircleAt: function(x,y,skin) {
with (this.ctx) {
save();
globalAlpha = skin.alpha;
lineWidth = skin.lineWidth;
if (!document.all)
beginPath();
arc(x, y, skin.radius, 0, 2*Math.PI, false);
if (skin.fillColor) {
fillStyle = skin.fillColor
fill();
}
else {
// XXX why not stroke and fill
strokeStyle = skin.color;
stroke();
}
restore();
}
},
radialLineAtAngle: function(angleFraction,skin) {
with (this.ctx) {
save();
translate(this.renderRadius,this.renderRadius);
rotate(Math.PI * (2 * angleFraction - 0.5));
globalAlpha = skin.alpha;
strokeStyle = skin.color;
lineWidth = skin.lineWidth;
if (skin.radius) {
this.fullCircleAt(skin.startAt,0,skin)
}
else {
beginPath();
moveTo(skin.startAt,0)
lineTo(skin.endAt,0);
stroke();
}
restore();
}
},
render: function(hour,min,sec) {
var skin = CoolClock.config.skins[this.skinId];
this.ctx.clearRect(0,0,this.renderRadius*2,this.renderRadius*2);
this.fullCircle(skin.outerBorder);
for (var i=0;i<60;i++)
this.radialLineAtAngle(i/60,skin[ i%5 ? "smallIndicator" : "largeIndicator"]);
this.radialLineAtAngle((hour+min/60)/12,skin.hourHand);
this.radialLineAtAngle((min+sec/60)/60,skin.minuteHand);
if (this.showSecondHand) {
this.radialLineAtAngle(sec/60,skin.secondHand);
this.radialLineAtAngle(sec/60,skin.secondDecoration);
}
},
nextTick: function() {
setTimeout("CoolClock.config.clockTracker['"+this.canvasId+"'].tick()",this.tickDelay);
},
stillHere: function() {
return document.getElementById(this.canvasId) != null;
},
refreshDisplay: function() {
var now = new Date();
this.render(now.getHours(),now.getMinutes(),now.getSeconds());
},
tick: function() {
if (this.stillHere()) {
this.refreshDisplay()
this.nextTick();
}
}
}
config.macros.clock2 = {
counter: 0,
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var size,skin,seconds,skinData;
for (var i=0;i<params.length;i++)
if (/^\d+$/.exec(params[i]))
size = params[i];
else if (params[i] == "noSeconds")
seconds = false;
else if (/^\{/.exec(params[i]))
eval("skinData = " + params[i]);
else
skin = params[i];
if (skinData) {
CoolClock.config.skins.customSkin = skinData;
skin = "customSkin";
}
var canvas = createTiddlyElement(place,"canvas","clockcanvas"+this.counter);
var clock = new CoolClock("clockcanvas"+this.counter,size,skin,seconds);
this.counter++;
}
}
//}}}
[[TiddlyTimeJournal]]
[[TimeJournal]]
/***
|''Name''|DeprecatedFunctionsPlugin|
|''Description''|Provides support for functions removed from the TiddlyWiki core|
|''Version''|1.0.0|
|''Status''|stable|
|''Source''|http://www.tiddlywiki.com/plugins.html#DeprecatedFunctionsPlugin|
|''~CodeRepository:''|http://svn.tiddlywiki.org/Trunk/association/plugins/DeprecatedFunctionsPlugin/DeprecatedFunctionsPlugin.js |
|''License''|[[BSD open source license]]|
|''~CoreVersion''|2.3.0|
|''Feedback''|[[TiddlyWiki community|http://groups.google.com/group/TiddlyWiki]] |
|''Keywords''|legacySupport|
!Code
***/
//{{{
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");
}
//}}}
{{ts{2008-08-18 10:13}}} First event
//~~(Part of the [[ForEachTiddlerPlugin]])~~//
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 : Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
''Using JavaScript''
To give you a lot of flexibility the [[ForEachTiddlerMacro]] uses JavaScript in its arguments. Even if you are not that familiar with JavaScript you may find forEachTiddler useful. Just have a look at the various ready-to-use [[ForEachTiddlerExamples|http://tiddlywiki.abego-software.de/#ForEachTiddlerExamples]] and adapt them to your needs.
''The Elements of the Macro''
The arguments of the ForEachTiddlerMacro consist of multiple parts, each of them being optional.
<<slider chkFETInClause [[inClause]] "inClause" "inClause">>
<<slider chkFETWhereClause [[whereClause]] "whereClause" "whereClause">>
<<slider chkFETSortClause [[sortClause]] "sortClause" "sortClause">>
<<slider chkFETScriptClause [[scriptClause]] "scriptClause" "scriptClause">>
<<slider chkFETActions [[Action Specification]] "Action Specification" "Action Specification">>
''Using Macros and ">" inside the forEachTiddler Macro''
You may use other macro calls into the expression, especially in the actionParameters. To avoid that the {{{>>}}} of such a macro call is misinterpreted as the end of the {{{<<forEachTiddler...>>}}} macro you must escape the {{{>>}}} of the inner macro with {{{$))}}} E.g. if you want to use {{{<<tiddler ...>>}}} inside the {{{forEachTiddler}}} macro you have to write {{{<<tiddler ...$))}}}.
In addition it is necessary to escape single {{{>}}} with the text {{{$)}}}.
''Using {{{<<tiddler ... with: ...>>}}} to re-use ForEachTiddler definitions''
Sometimes you may want to use a certain ForEachTiddler definition in slight variations. E.g. you may want to list either the tiddlers tagged with "ToDo" and in the other case with "Done". To do so you may use "Tiddler parameters". Here an example:
Replace the variable part of the ForEachTiddler definition with $1 ($2,... $9 are supported). E.g. you may create the tiddler "ListTaggedTiddlers" like this
{{{
<<forEachTiddler
where
'tiddler.tags.contains("$1")'
>>
}}}
Now you can use the ListTaggedTiddlers for various specific tags, using the {{{<<tiddler ...>>}}} macro:
{{{
<<tiddler ListTaggedTiddlers with: "systemConfig">>
}}}
{{{
<<tiddler ListTaggedTiddlers with: "Plugin">>
}}}
See also [[ForEachTiddlerExamples|http://tiddlywiki.abego-software.de/#ForEachTiddlerExamples]].
/***
|''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 : Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples|http://tiddlywiki.abego-software.de/#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.
***/
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
/***
|Name:|InstantTimestampPlugin|
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10a ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
!!Notes
* Change the timeFormat and dateFormat below to suit your preference. (done EW: version adjusted 1.0.10a)
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.
***/
//{{{
config.InstantTimestamp = {
// adjust to suit
timeFormat: 'YYYY-0MM-DD 0hh:0mm',
dateFormat: 'YYYY-0MM-DD',
translations: [
[/^!ts?$/img, "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/^!ds?$/img, "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],
// thanks Adapted Cat
[/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
[/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"]
],
excludeTags: [
"noAutoCorrect",
"noTimestamp",
"html",
"CSS",
"css",
"systemConfig",
"systemConfigDisabled",
"zsystemConfig",
"Plugins",
"Plugin",
"plugins",
"plugin",
"javascript",
"code",
"systemTheme",
"systemPalette"
],
excludeTiddlers: [
"StyleSheet",
"StyleSheetLayout",
"StyleSheetColors",
"StyleSheetPrint"
// more?
]
};
TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
tags = tags ? tags : []; // just in case tags is null
tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
var conf = config.InstantTimestamp;
if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {
var now = new Date();
var trans = conf.translations;
for (var i=0;i<trans.length;i++) {
newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
}
}
// TODO: use apply() instead of naming all args?
return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
}
// you can override these in StyleSheet
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");
//}}}
<html><font size=4><b>B</b></font></html>efore you begin using ''~TiddlyTimeJournal'' make a note (//in writing//) of how you think your time is spent: surfing the web, on the phone, answering email, meeting visitors //etc.//
!Next
If you haven't done so already, click [[GettingStarted]] enter your name in the box provided for your //username//. You may also change the SiteTitle and SiteSubtitle shown above.
Now, practise logging some activities by starting and stopping the timers. When you are ready, delete the ActivityReport, [[Interruptions]] and EventLog tiddlers and that for [[18 August 2008]] and create your own.
Bookmark ''~TiddlyTimeJournal'' in your browser. Keep it open in a tab and use it for a few days. Then compare how your time is actually spent with what you thought before you began. Continue logging //ad lib.//
!To begin
Just click on the timer of your choice: the
* ''~ActivityReport'' timer (under the clock) for any activity you wish to record in the ~ActivityReport log (multiple activities in the same log).
* ''Other'' timer for activities you wish to record separately. You will be prompted for the log ("tiddler") to use. You might wish to record some activities by project, client, country, class etc.
Everything else is considered an interruption and each may be recorded with the appropriate timer. Four kinds have been defined: phone calls, visits, breaks, and "other" kinds which you will be prompted to describe individually. You may add to or edit this list of defined interrupts by editing the main menu (click [[menu|MainMenu]] on the left). Interruptions may also be logged in the ActivityReport or to individually named reports, at your discretion, using the first and second timers respectively.
You can export and delete or rename the ActivityReport and [[Interruptions]] and other logs (~TiddlyWiki "tiddlers") whenever you're ready to start new ones.
To review your activities at any time, including how much time has been lost to interruptions, just click on TimeJournal above the clock.
!Note
You may keep a simple manual record of events, milestones //etc.// by editing a tiddler (''new tiddler'' on the menu on the right) and entering ''{/%%/ds}'' or ''{ts}'' to record a date or timestamp when the tiddler is saved. See EventLog, //e.g.//, and InstantTimestamp for date formatting options. To have it included in your TimeJournal report just tag it with the word ''task''.
|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|
|2008-08-17|Phone CSL|18:39:46|18:40:17|00:00:30|
/%tasktimer%/
/***
|Name:|LessBackupsPlugin|
|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1 ($Rev: 2320 $)|
|Date:|$Date: 2007-06-18 22:37:46 +1000 (Mon, 18 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/#LessBackupsPlugin|
|Author:|Simon Baird|
|Email:|simon.baird@gmail.com|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Description
You end up with just backup one per year, per month, per weekday, per hour, minute, and second. So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
!!Notes
Works in IE and Firefox only. Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.
***/
//{{{
var MINS = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS = 24 * HOURS;
if (!config.lessBackups) {
config.lessBackups = {
// comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
modes: [
["YYYY", 365*DAYS], // one per year for ever
["MMM", 31*DAYS], // one per month
["ddd", 7*DAYS], // one per weekday
//["d0DD", 1*DAYS], // one per day of month
["h0hh", 24*HOURS], // one per hour
["m0mm", 1*HOURS], // one per minute
["s0ss", 1*MINS], // one per second
["latest",0] // always keep last version. (leave this).
]
};
}
window.getSpecialBackupPath = function(backupPath) {
var now = new Date();
var modes = config.lessBackups.modes;
for (var i=0;i<modes.length;i++) {
// the filename we will try
var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,
'$1'+now.formatString(modes[i][0]).toLowerCase()+'$3')
// open the file
try {
if (config.browser.isIE) {
var fsobject = new ActiveXObject("Scripting.FileSystemObject")
var fileExists = fsobject.FileExists(specialBackupPath);
if (fileExists) {
var fileObject = fsobject.GetFile(specialBackupPath);
var modDate = new Date(fileObject.DateLastModified).valueOf();
}
}
else {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(specialBackupPath);
var fileExists = file.exists();
if (fileExists) {
var modDate = file.lastModifiedTime;
}
}
}
catch(e) {
// give up
return backupPath;
}
// expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
// June file on disk that's more than an month old then it must be stale so overwrite
// note that "latest" should be always written because the expiration period is zero (see above)
var expiry = new Date(modDate + modes[i][1]);
if (!fileExists || now > expiry)
return specialBackupPath;
}
}
// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));
}
//}}}
/***
|Author:|Simon Baird|
|URL:|http://linktomemacro.tiddlyspot.com/|
As suggested by Peter Lindsay on 17-Nov-2006. Example usage:
{{{<<linkToMe>>, <<linkToMe 'right click here to download'>>}}}
<<linkToMe>>, <<linkToMe 'right click here to download'>>
***/
//{{{
merge(config.macros,{
linkToMe: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
wikify('<html><a href="'+window.location.href+'">'+(params[0]?params[0]:window.location.href)+'</a></html>',place,null,tiddler);
}}
});
//}}}
<html><font size=4><b>Main Activities</b></font></html>
[[TimeJournal]]
<<clock2 40>>
<<taskTimer "ActivityReport" "|%4|%0|%1|%2|%3|\n" "Activity description" "">>
''Log to:'' ActivityReport
<<taskTimer ask "|%4|%0|%1|%2|%3|\n" "Activity description" "">>
''Log to:'' Other
----
<html><font size=4><b>Interrupts</b></font></html>
''Phone'' <<taskTimer "Interruptions" "|%4|%0|%1|%2|%3|\n" "Phone call with: " "Phone: ">>
''Visit'' <<taskTimer "Interruptions" "|%4|%0|%1|%2|%3|\n" "Visited with: " "Visit: ">>
''Break'' <<taskTimer "Interruptions" "|%4|%0|%1|%2|%3|\n" "Break for: " "">>
''Other'' <<taskTimer "Interruptions" "|%4|%0|%1|%2|%3|\n" "Interrupt for: " "">>
''Log to:'' [[Interruptions]]
----
Edit this [[menu|MainMenu]].
<<toggleSideBar Sidebar "Show / Hide Sidebar" show>>
/***
|Name|SaveOnExitPlugin|
|Source|http://www.TiddlyTools.com/#SaveOnExitPlugin|
|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|plugin|
|Requires||
|Overrides|window.confirmExit|
|Options|##Configuration|
|Description|extra safety when exiting with unsaved changes|
For extra "data safety" when exiting from a TiddlyWiki document, this plugin prompts you to ''//save any tiddlers that are still being actively edited//''. The plugin then provides an additional option to ''//save the entire TiddlyWiki document//'' before continuing. Finally, if you do not choose to save the file and there are still unsaved tiddler changes, the standard TiddlyWiki warning message is then displayed as usual, with options to ''//stay on the current page or exit and lose all changes.//''
!!!!!Configuration
<<<
<<option chkSaveOnExit>> Enable "save-before-exiting" confirmation messages
<<<
!!!!!Revisions
<<<
2008.04.03 2.0.0 completely re-written to provide checks for active tiddler editors and more consistent warning messages
2007.03.01 1.0.2 use apply() to invoke hijacked core function
2006.08.23 1.0.1 Re-released. Note default is now to NOT enable second message. (i.e., standard behavior)
2006.02.24 1.0.0 Initial release. Replaces ConfirmExitPlugin, which is now included in the TW core functionality.
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveOnExit = {major: 2, minor: 0, revision: 0, date: new Date(2008,4,3)};
// do NOT enable safety checks by default (i.e., use standard behavior unless explicitly enabled)
if (config.options.chkSaveOnExit===undefined) config.options.chkSaveOnExit=false;
config.messages.activeEditorWarning=
"Are you sure you want to navigate away from this page?"
+"\n\n--------------------------------\n\n"
+"'%0' is currently being edited."
+"\n\n--------------------------------\n\n"
+"Press OK to save this tiddler, or Cancel to skip this tiddler and continue.";
config.messages.unsavedChangesWarning=
"Are you sure you want to navigate away from this page?"
+"\n\n--------------------------------\n\n"
+"There are unsaved changes in this TiddlyWiki document."
+"\n\n--------------------------------\n\n"
+"Press OK to save the document, or Cancel to continue without saving.";
// for browsers that support onBeforeUnload event handling
window.saveOnExit_coreConfirmExit=window.confirmExit;
window.confirmExit=function() {
// call core handler (to invoke other hijacked 'on exit' code, e.g., [[StorySaverPlugin]])
window.saveOnExit_coreConfirmExit.apply(this,arguments);
// check for tiddlers being edited and offer chance to save/close each
if (config.options.chkSaveOnExit) story.forEachTiddler(function(tid,elem) {
if (elem.getAttribute("dirty")!="true") return;
if (!confirm(config.messages.activeEditorWarning.format([tid]))) return;
story.saveTiddler(tid);
story.closeTiddler(tid);
});
// check for unsaved changes
if(store && store.isDirty && store.isDirty()) {
if (config.options.chkSaveOnExit && confirm(config.messages.unsavedChangesWarning))
saveChanges(); // optionally, save the file before exiting
else
return config.messages.confirmExit; // otherwise, show standard warning message
}
}
// for older browsers that only support onUnload event handling
window.checkUnsavedChanges=function() { if(window.hadConfirmExit === false) window.confirmExit(); }
//}}}
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler(), Story.prototype.displayTiddlers()|
|Options|##Configuration|
|Description|Show tiddlers one at a time with automatic permalink, or always open tiddlers at top/bottom of page.|
This plugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one tiddler displayed at a time.
!!!!!Documentation
>see [[SinglePageModePluginInfo]]
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)
Notes:
* The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}.
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2008.06.12 [2.9.5] corrected 'scroll to top of page' logic in auto-scroll handling
| Please see [[SinglePageModePluginInfo]] for previous revision details |
2005.08.15 [1.0.0] Initial Release. Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts.
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageMode= {major: 2, minor: 9, revision: 5, date: new Date(2008,6,12)};
//}}}
//{{{
config.paramifiers.SPM = { onstart: function(v) {
config.options.chkSinglePageMode=eval(v);
if (config.options.chkSinglePageMode && config.options.chkSinglePagePermalink && !config.browser.isSafari) {
config.lastURL = window.location.hash;
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
} };
//}}}
//{{{
if (config.options.chkSinglePageMode==undefined)
config.options.chkSinglePageMode=false;
if (config.options.chkSinglePagePermalink==undefined)
config.options.chkSinglePagePermalink=true;
if (config.options.chkSinglePageKeepFoldedTiddlers==undefined)
config.options.chkSinglePageKeepFoldedTiddlers=false;
if (config.options.chkSinglePageKeepEditedTiddlers==undefined)
config.options.chkSinglePageKeepEditedTiddlers=false;
if (config.options.chkTopOfPageMode==undefined)
config.options.chkTopOfPageMode=false;
if (config.options.chkBottomOfPageMode==undefined)
config.options.chkBottomOfPageMode=false;
if (config.options.chkSinglePageAutoScroll==undefined)
config.options.chkSinglePageAutoScroll=true;
//}}}
//{{{
config.SPMTimer = 0;
config.lastURL = window.location.hash;
function checkLastURL()
{
if (!config.options.chkSinglePageMode)
{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
if (config.lastURL == window.location.hash) return; // no change in hash
var tids=decodeURIComponent(window.location.hash.substr(1)).readBracketedList();
if (tids.length==1) // permalink (single tiddler in URL)
story.displayTiddler(null,tids[0]);
else { // restore permaview or default view
config.lastURL = window.location.hash;
if (!tids.length) tids=store.getTiddlerText("DefaultTiddlers").readBracketedList();
story.closeAllTiddlers();
story.displayTiddlers(null,tids);
}
}
if (Story.prototype.SPM_coreDisplayTiddler==undefined)
Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
{
var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
var tiddlerElem=document.getElementById(story.idPrefix+title); // ==null unless tiddler is already displayed
var opt=config.options;
var single=opt.chkSinglePageMode && !startingUp;
var top=opt.chkTopOfPageMode && !startingUp;
var bottom=opt.chkBottomOfPageMode && !startingUp;
if (single) {
story.forEachTiddler(function(tid,elem) {
// skip current tiddler and, optionally, tiddlers that are folded.
if ( tid==title
|| (opt.chkSinglePageKeepFoldedTiddlers && elem.getAttribute("folded")=="true"))
return;
// if a tiddler is being edited, ask before closing
if (elem.getAttribute("dirty")=="true") {
if (opt.chkSinglePageKeepEditedTiddlers) return;
// if tiddler to be displayed is already shown, then leave active tiddler editor as is
// (occurs when switching between view and edit modes)
if (tiddlerElem) return;
// otherwise, ask for permission
var msg="'"+tid+"' is currently being edited.\n\n";
msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
if (!confirm(msg)) return; else story.saveTiddler(tid);
}
story.closeTiddler(tid);
});
}
else if (top)
arguments[0]=null;
else if (bottom)
arguments[0]="bottom";
if (single && opt.chkSinglePagePermalink && !config.browser.isSafari) {
window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
config.lastURL = window.location.hash;
document.title = wikifyPlain("SiteTitle") + " - " + title;
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
if (tiddlerElem && tiddlerElem.getAttribute("dirty")=="true") { // editing... move tiddler without re-rendering
var isTopTiddler=(tiddlerElem.previousSibling==null);
if (!isTopTiddler && (single || top))
tiddlerElem.parentNode.insertBefore(tiddlerElem,tiddlerElem.parentNode.firstChild);
else if (bottom)
tiddlerElem.parentNode.insertBefore(tiddlerElem,null);
else this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
} else
this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
var tiddlerElem=document.getElementById(story.idPrefix+title);
if (tiddlerElem&&opt.chkSinglePageAutoScroll) {
// scroll to top of page or top of tiddler
var isTopTiddler=(tiddlerElem.previousSibling==null);
var yPos=isTopTiddler?0:ensureVisible(tiddlerElem);
// if animating, defer scroll until 200ms after animation completes
var delay=opt.chkAnimate?config.animDuration+200:0;
setTimeout("window.scrollTo(0,"+yPos+")",delay);
}
}
if (Story.prototype.SPM_coreDisplayTiddlers==undefined)
Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function() {
// suspend single/top/bottom modes when showing multiple tiddlers
var opt=config.options;
var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
this.SPM_coreDisplayTiddlers.apply(this,arguments);
opt.chkBottomOfPageMode=saveBPM;
opt.chkTopOfPageMode=saveTPM;
opt.chkSinglePageMode=saveSPM;
}
//}}}
/***
|Name|SinglePageModePluginInfo|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for SinglePageModePlugin|
Normally, as you click on the links in TiddlyWiki, more and more tiddlers are displayed on the page. The order of this tiddler display depends upon when and where you have clicked. Some people like this non-linear method of reading the document, while others have reported that when many tiddlers have been opened, it can get somewhat confusing. SinglePageModePlugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time.
!!!!!Usage
<<<
When the plugin is enabled, only one tiddler will be displayed at a time and the browser window's titlebar is updated to include the current tiddler title. The browser's location URL is also updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler. Alternatively, even when displaying multiple tiddlers //is// permitted, you can still reduce the potential for confusion by forcing tiddlers to always open at the top (or bottom) of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)
Notes:
* {{block{
The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}. You can also use {{{SPM:expression}}}, where 'expression' is any javascript statement that evaluates to true or false. This allows you to create hard-coded links in other documents that can selectively enable/disable the use of this option based on various programmatic conditions, such as the current username. For example, using
{{{#SPM:config.options.txtUserName!="SomeName"}}}
enables 'one tiddler at a time' display for all users //other than// "~SomeName")}}}
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2008.06.12 [2.9.5] corrected 'scroll to top of page' logic in auto-scroll handling
2008.06.11 [2.9.4] added chkSinglePageKeepEditedTiddlers option
2008.06.05 [2.9.3] in displayTiddler(), bypass single/top/bottom mode handling if startingUp. Allows multiple tiddlers to be displayed during startup processing (e.g., #story:DefaultTiddlers), even if single/top/bottom mode is enabled.
2008.04.18 [2.9.2] in displayTiddler() and checkLastURL(), handling for Unicode in tiddler titles (remove explicit conversion between Unicode and UTF, as this is apparently done automatically by encode/decodeURIComponent, resulting in double-encoding!
2008.04.08 [2.9.1] don't automatically add options to AdvancedOptions shadow tiddler
2008.04.02 [2.9.0] in displayTiddler(), when single-page mode is in use and a tiddler is being edited, ask for permission to save-and-close that tiddler, instead of just leaving it open.
2008.03.29 [2.8.3] in displayTiddler(), get title from tiddler object (if needed). Fixes errors caused when calling function passes a tiddler *object* instead of a tiddler *title*
2008.03.14 [2.8.2] in displayTiddler(), if editing specified tiddler, just move it to top/bottom of story *without* re-rendering (prevents discard of partial edits).
2008.03.06 [2.8.1] in paramifier handler, start 'checkURL' timer if chkSinglePageMode is enabled
2008.03.06 [2.8.0] added option, {{{config.options.chkSinglePageKeepFoldedTiddlers}}}, so folded tiddlers won't be closed when using single-page mode. Also, in checkURL(), if hash is a ''permaview'' (e.g., "#foo bar baz"), then display multiple tiddlers rather than attempting to display "foo bar baz" as a single tiddler
2008.03.05 [2.7.0] added support for "SPM:" URL paramifier
2008.03.01 [2.6.0] in hijack of displayTiddler(), added 'title' argument to closeAllTiddlers() so that target tiddler isn't closed-and-reopened if it was already displayed. Also, added config.options.chkSinglePageAutoScrolloption to bypass automatic 'scroll into view' logic (note: core still does it's own ensureVisible() handling)
2007.12.22 [2.5.3] in checkLastURL(), use decodeURIComponent() instead of decodeURI so that tiddler titles with commas (and/or other punctuation) are correctly handled.
2007.10.26 [2.5.2] documentation cleanup
2007.10.08 [2.5.1] in displayTiddler(), when using single-page or top-of-page mode, scrollTo(0,0) to ensure that page header is in view.
2007.09.13 [2.5.0] for TPM/BPM modes, don't force tiddler to redisplay if already shown. Allows transition between view/edit or collapsed/view templates, without repositioning displayed tiddler.
2007.09.12 [2.4.0] added option to disable automatic permalink feature. Also, Safari is now excluded from permalinking action to avoid bug where tiddlers don't display after hash is updated.
2007.03.03 [2.3.1] fix typo when adding BPM option to AdvancedOptions (prevented checkbox from appearing)
2007.03.03 [2.3.0] added support for BottomOfPageMode (BPM) based on request from DaveGarbutt
2007.02.06 [2.2.3] in Story.prototype.displayTiddler(), use convertUnicodeToUTF8() for correct I18N string handling when creating URL hash string from tiddler title (based on bug report from BidiX)
2007.01.08 [2.2.2] use apply() to invoke hijacked core functions
2006.07.04 [2.2.1] in hijack for displayTiddlers(), suspend TPM as well as SPM so that DefaultTiddlers displays in the correct order.
2006.06.01 [2.2.0] added chkTopOfPageMode (TPM) handling
2006.02.04 [2.1.1] moved global variable declarations to config.* to avoid FireFox 1.5.0.1 crash bug when assigning to globals
2005.12.27 [2.1.0] hijack displayTiddlers() so that SPM can be suspended during startup while displaying the DefaultTiddlers (or #hash list). Also, corrected initialization for undefined SPM flag to "false", so default behavior is to display multiple tiddlers
2005.12.27 [2.0.0] Update for TW2.0
2005.11.24 [1.1.2] When the back and forward buttons are used, the page now changes to match the URL. Based on code added by Clint Checketts
2005.10.14 [1.1.1] permalink creation now calls encodeTiddlyLink() to handle tiddler titles with spaces in them
2005.10.14 [1.1.0] added automatic setting of window title and location bar ('auto-permalink'). feature suggestion by David Dickens.
2005.10.09 [1.0.1] combined documentation and code in a single tiddler
2005.08.15 [1.0.0] Initial Release
<<<
^^0.9^^~~//for Firefox//~~
//Managing your time well makes you successful// ~~[[Randy Pausch|http://en.wikipedia.org/wiki/Randy_pausch]]~~
<<timeline better:true excludeTag:hide sortBy:modified>>
Tiddlers that are tagged with<<tag task>>can be used to ''describe specific tasks'' and ''assign'' them to individuals, ''track'' the status (e.g., "not started", "in progress", "done", etc.), and ''record elapsed time'' of specific activities connected to a given task.
Task tiddlers are displayed using a custom [[TaskViewTemplate]], which automatically embeds extra task-related controls directly in the tiddler //view//, allowing you to quickly ''assign and track task progress, without needing to edit the tiddler content.''
''To start a new task, simply create a tiddler, enter some text (e.g., notes about the task), add tag<<tag task>>, and then press 'done' to start viewing the tiddler.'' Alternatively, you can add the following """<<newTiddler>>""" macro in your SideBarOptions (or any other tiddler) to insert a<<newTiddler label:'new task' title:'NewTask' tag:'task' prompt:'create a task tiddler'>>command into your document:
{{{
<<newTiddler label:'new task' title:'NewTask' tag:'task' prompt:'create a task tiddler'>>
}}}
/***
|Name|TaskTimerPlugin|
|Source|http://www.TiddlyTools.com/#TaskTimerPlugin|
|Documentation|http://www.TiddlyTools.com/#TaskTimerPluginInfo|
|Version|1.3.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|'timer' button automatically writes start/end/elapsed time into tiddler content|
Quickly generate 'timed task' logs that can be used for status reports, billing purposes, etc.
!!!!!Documentation
> see [[TaskTimerPluginInfo]]
!!!!!Configuration
> see [[TaskTimerPluginConfig]]
!!!!!Revisions
<<<
2008.03.12 [1.3.0] added 'datestampFormat' for including date in standard output.<br>Also, for clarity, renamed 'getDateFormat()' to 'getJournalFormat()'.
2008.03.10 [*.*.*] plugin size reduction - documentation moved to [[TaskTimerPluginInfo]]
2007.12.13 [1.2.2] in getDateFormat(), cleanup fallback logic
|please see [[TaskTimerPluginInfo]] for additional revision details|
2007.03.14 [0.5.0] converted from inline script
<<<
!!!!!Code
***/
//{{{
version.extensions.taskTimer= {major: 1, minor:3, revision: 0, date: new Date(2008,3,12)};
config.macros.taskTimer = {
label: "start timer",
title: "press to start the task timer",
format: "|%4|%0|%1|%2|%3|\\n", // note: double-backslash-en, also date is %4 (for backward compatibility)
defText: " ", // default description text
todayKeyword: "today",
todayFormat: "0MM/0DD/YYYY", // default format - superceded by CalendarPlugin, DatePlugin, or DatePluginConfig
datestampFormat: "YYYY-0MM-0DD", // date stamp format
defHeader: "|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|\n",
defTarget: "ActivityReport",
prompt: "Enter a short description for this activity. Press [cancel] to continue timer.",
askMsg: "Enter the title of a tiddler in which to record this activity. Press [cancel] to continue timer.",
createdMsg: "'%0' has been created",
updatedMsg: "'%0' has been updated",
marker: "/%"+"tasktimer"+"%/",
tag: "task",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var target=params.shift(); // get optional target tiddler title
if (!target) target="";
var format=this.format; if (params[0]) format=params.shift(); // get optional output format
var prompt=this.prompt; if (params[0]) prompt=params.shift(); // get optional prompt text
var defText=this.defText; if (params[0]) defText=params.shift(); // get optional default text
var onclick="config.macros.taskTimer.toggle(this,'"+target+"','"+format+"','"+prompt+"','"+defText+"')";
createTiddlyElement(place,"span").innerHTML =
'<input type="button" value="start timer" title="'+this.title+'" onclick="'+onclick+'">';
},
toggle: function(here,target,format,msg,defText) {
if (!target || !target.length || target=="here") {
var tid=story.findContainingTiddler(here);
target=tid?tid.getAttribute("tiddler"):"ask";
}
if (!here.running) { // not running... start timer...
var now=new Date();
here.startTime=now;
here.title=(here.target?here.target:target)+" - "+now.formatString("started at 0hh:0mm:0ss");
here.value=now.formatString("0hh:0mm:0ss - 00:00:00");
here.id=(new Date()).convertToYYYYMMDDHHMMSSMMM()+Math.random().toString(); // unique ID
here.ticker=setTimeout("config.macros.taskTimer.tick('"+here.id+"')",500);
here.running=true;
} else {
if (target=="ask") {
target=prompt(this.askMsg,here.target?here.target:this.defTarget);
if (!target) return; // user cancelled input... continue timer
}
var txt=prompt(msg,defText); // get description from user
if (!txt) return; // user cancelled input... continue timer
if (target==this.todayKeyword || target.substr(0,this.todayKeyword.length+1)==this.todayKeyword+":")
target=(new Date()).formatString(this.getJournalFormat(target));
here=document.getElementById(here.id); // RE-get button element after timer has stopped...
clearTimeout(here.ticker);
here.target=target;
var before=this.defHeader;
var after=this.marker+"\n";
var tiddler=store.getTiddler(here.target);
if (tiddler && tiddler.text.length) {
var pos=tiddler.text.indexOf(this.marker);
if (pos==-1) pos=tiddler.text.length; // no marker, append content to end
var before=tiddler.text.substr(0,pos); // everything up to marker
if (before.length&&before.substr(before.length-1)!="\n") before+="\n"; // start on a new line
var after=tiddler.text.substr(pos); // marker+everything else
}
var start=here.startTime.formatString("0hh:0mm:0ss");
var now=new Date();
var stop=now.formatString("0hh:0mm:0ss");
var diff=new Date(now-here.startTime);
var s=diff.getUTCSeconds(); if (s<10) s="0"+s;
var m=diff.getUTCMinutes(); if (m<10) m="0"+m;
var h=diff.getUTCHours(); if (h<10) h="0"+h;
var elapsed=h+":"+m+":"+s;
var dateStamp=now.formatString(config.macros.taskTimer.datestampFormat);
var newtxt=before+format.format([txt,start,stop,elapsed,dateStamp])+after;
var newtags=(tiddler?tiddler.tags:['task']); // include 'task' tag when creating new tiddlers
store.saveTiddler(here.target,here.target,newtxt,config.options.txtUserName,new Date(),newtags,tiddler?tiddler.fields:null);
if (!tiddler) displayMessage(this.createdMsg.format([here.target]));
else displayMessage(this.updatedMsg.format([here.target]));
here.running=false;
here.value=this.label;
here.title=this.title;
var tid=story.findContainingTiddler(here);
if (!tid || tid.getAttribute("tiddler")!=target) // display target tiddler, but only when button is not IN the target tiddler
{ story.displayTiddler(story.findContainingTiddler(here),here.target); story.refreshTiddler(here.target,1,true); }
}
},
tick: function(id) {
var here=document.getElementById(id); if (!here) return;
var now=new Date();
var diff=new Date(now-here.startTime);
var s=diff.getUTCSeconds(); if (s<10) s="0"+s;
var m=diff.getUTCMinutes(); if (m<10) m="0"+m;
var h=diff.getUTCHours(); if (h<10) h="0"+h;
var elapsed=h+":"+m+":"+s;
here.value=now.formatString("0hh:0mm:0ss")+" - "+elapsed;
here.ticker=setTimeout("config.macros.taskTimer.tick('"+id+"')",500);
},
getJournalFormat: function(target) {
var fmt=target.split(":"); fmt.shift(); fmt=fmt.join(":");
if (!fmt || !fmt.length) { // if date format was not specified
if (config.macros.date) // if installed, use default from DatePlugin
fmt=config.macros.date.linkformat;
if (config.macros.calendar) { // if installed, use default from CalendarPlugin
if (!config.macros.date) // hard-coded calendar fallback if no DatePlugin
fmt=config.macros.calendar.tiddlerformat;
else // journalDateFmt is set when calendar is rendered with DatePlugin
fmt=config.macros.calendar.journalDateFmt;
}
}
if (!fmt) { // if not specified and no DatePlugin/CalendarPlugin
// get format from <<newJournal>> in SideBarOptions
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]) fmt = pa[0]; }
}
if (!fmt) var fmt=this.todayFormat; // no "newJournal"... final fallback.
return fmt;
}
}
//}}}
/***
|Name|TaskTimerPluginConfig|
|Source|http://www.TiddlyTools.com/#TaskTimerPluginConfig|
|Documentation|http://www.TiddlyTools.com/#TaskTimerPluginInfo|
|Version|1.3.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|formats other optional settings for TaskTimerPlugin|
***/
//{{{
// default target tiddler title (when 'ask' option is used)
config.macros.taskTimer.defTarget="ActivityReport";
// table heading (when creating **new** target tiddlers only)
config.macros.taskTimer.defHeader="|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|\n";
// note: double-backslash-en, also datestamp is %4 (for backward compatibility)
config.macros.taskTimer.format="|%4|%0|%1|%2|%3|\\n";
// date stamp format (used with %4, above)
config.macros.taskTimer.datestampFormat="YYYY-0MM-0DD";
// default description text - note: do not use empty string (e.g., "")
config.macros.taskTimer.defText=" ";
// format for target tiddler title (when "today" option is used)
// otherwise, value is superceded by CalendarPlugin, DatePlugin, DatePluginConfig,
// or format from <<newJournal>> macro embedded in SideBarOptions
config.macros.taskTimer.todayFormat="0MM/0DD/YYYY";
// marker for locating 'insertion point' in target tiddler
config.macros.taskTimer.marker="/%"+"tasktimer"+"%/"; //
// default tag (when creating **new** target tiddlers only)
config.macros.taskTimer.tag="task";
//}}}
/***
|Name|TaskTimerPlugin|
|Source|http://www.TiddlyTools.com/#TaskTimerPlugin|
|Documentation|http://www.TiddlyTools.com/#TaskTimerPluginInfo|
|Version|1.3.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|docmentation|
|Requires||
|Overrides||
|Description|documentation for TaskTimerPlugin|
Quickly generate 'timed task' logs that can be used for status reports, billing purposes, etc.
!!!!!Usage
<<<
{{{<<taskTimer TiddlerName "output format" "prompt text" "default description">>}}}
displays a pushbutton that, when pressed, prompts for a 'target tiddler', and then displays the current time and elapsed time on the button, updated automatically each second. Pressing the button again will stop the timer, prompt for a 'task description' and then write the description, starttime, endtime, and elapsed time into the target tiddler content.
''~TiddlerName'' //or// ''ask'' //or// ''here'' //or// ''today'' //or// ''"""today:YYYY0MM0DD"""''
>If you omit the ''~TiddlerName'' parameter or use the keyword, ''here'', the output is inserted into the current tiddler. If you use the keyword, ''ask'', then you will be prompted for a ~TiddlerName each time you press the button to start the timer. If you use the keyword, ''today'', then the current date is used as the ~TiddlerName. You can specify any date format you like by appending it to the "today:" keyword. By default, if the format is omitted from the paramter, the date format will match that used by {{{<<newJournal>>}}} macro or the {{{<<date>>}}} and {{{<<calendar>>}}} macros (if [[DatePlugin]] and/or [[CalendarPlugin]] are installed).
>
>If the target tiddler does not yet exist, it will be automatically created when a timer activity is recorded for the first time. Note: When used in a non-tiddler area (such as MainMenu), you should either provide a specific ~TiddlerName value (e.g., {{{<<taskTimer MainMenu>>}}} or use the ''ask'' or '''today'' keywords.
''output format''
>The default output format is: {{{|%4|%0|%1|%2|%3|}}} where %0, %1, %2, %3 and %4 are automatically replaced with the description, starttime, stoptime, elapsed time and current date values, respectively. This format generates a single row using TiddlyWiki table format, allowing each subsequent timed task to add another row to an existing table of recorded activities. If this table format is not appropriate for your needs, you can provide an alternative formatting string, using the %n substitution markers to place those values where you want.
>
>//Please note: ''Do not use either single-quotes or double-quotes within the format string, as this interferes with the plugin's button generating code. Also, for backward-compatibility with previous versions of this plugin, the date value is indicated using the %4 'substitution marker', even though it is displayed as the first item in the table row.''//
''insertion point marker''
>The task timer output is usually appended to the end of the target tiddler content. However, you may choose to insert the output //anywhere// within the tiddler content simply by embedding an 'insertion point marker', consisting of the keyword "tasktimer", enclosed in TW style comments, like this: ''{{{/%}}}{{{tasktimer}}}{{{%/}}}''. When the marker is present in the tiddler source, the timed task report output is placed immediately //before// that marker, instead of at the end of the tiddler.
<<<
!!!!!Configuration
<<<
You can further customize the formats used by creating a separate tiddler, e.g. [[TaskTimerPluginConfig]], tagged with<<tag systemConfig>>, that contains any combination of the following javascript statements:
{{{
// default target tiddler title (when 'ask' option is used)
config.macros.taskTimer.defTarget="ActivityReport";
// table heading (when creating **new** target tiddlers only)
config.macros.taskTimer.defHeader="|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|\n";
// note: double-backslash-en, also datestamp is %4 (for backward compatibility)
config.macros.taskTimer.format="|%4|%0|%1|%2|%3|\\n";
// date stamp format (used with %4, above)
config.macros.taskTimer.datestampFormat="YYYY-0MM-0DD";
// default description text - note: do not use empty string (e.g., "")
config.macros.taskTimer.defText=" ";
// format for target tiddler title (when "today" option is used)
// otherwise, value is superceded by superceded by CalendarPlugin, DatePlugin, DatePluginConfig,
// or format from <<newJournal>> macro embedded in SideBarOptions
config.macros.taskTimer.todayFormat="0MM/0DD/YYYY";
// marker for locating 'insertion point' in target tiddler
config.macros.taskTimer.marker="/%tasktimer%/";
// default tag (when creating **new** target tiddlers only)
config.macros.taskTimer.tag="task";
}}}
<<<
!!!!!Examples
<<<
{{{<<taskTimer>>}}}
<<taskTimer>>
|//Date//|//Description//|//Started//|//Stopped//|//Elapsed//|
/%tasktimer%/
{{{<<taskTimer ask>>}}}
<<taskTimer ask>>
<<<
!!!!!Revisions
<<<
2008.03.12 [1.3.0] added 'datestampFormat' for including date in standard output. Also, for clarity, renamed 'getDateFormat()' to 'getJournalFormat()'.
2008.03.10 [*.*.*] plugin size reduction - documentation moved to [[TaskTimerPluginInfo]]
2007.12.13 [1.2.2] in getDateFormat(), cleanup fallback logic
2007.06.28 [1.2.1] pass current tiddler.fields to saveTiddler(), so updates to existing tiddler won't lose custom fields
2007.06.25 [1.2.0] added optional "default text" param for specifying the default description for new activity log entries
2007.06.22 [1.1.0] added "today" and "today:MMDDYYYY" as special keywords. Generates tiddlername from current date, and uses date format defined in CalendarPlugin, DatePlugin, or DatePluginConfig if any of those tiddlers is installed. Also, don't stop timer until user completes entering of prompted inputs (e.g., after asking for a target tiddler and activity description)
2007.05.22 [1.0.0] target tiddler created when stopping timer button (i.e., second button press) instead of when starting timer. Default header content includes comment marker. Target tiddler is tagged with "task".
2007.04.04 [0.8.2] moved handling for 'here' param into toggle(). In toggle(), only render target tiddler if button is not in that tiddler... fixes problem where starting timer with target=here was re-rendering (and thus re-initializing) the timer button (immediately stopping the timer)
2007.03.21 [0.8.1] handle case where target tiddler is deleted while timer is running.
2007.03.21 [0.8.0] use UTC time functions to calculate elapsed time in hours, minutes, and seconds
2007.03.20 [0.7.0] added lots of cool features, like automatically creating tiddlers, with prompting, etc.
2007.03.14 [0.5.0] converted from inline script
<<<
<!--{{{-->
<!--
|Name|TaskViewTemplate|
|Source|http://www.TiddlyTools.com/#TaskViewTemplate|
|Version||
|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|template|
|Requires|ToolbarCommands, TaggedTemplateTweak, ListboxPlugin, CheckboxPlugin, TaskTimerPlugin, WikifyPlugin, NestedSlidersPlugin, MoveablePanelPlugin, CommentPlugin, ExpandSlidersScript |
|Overrides||
|Description|custom version of view template used when tiddler is tagged with "task"|
-->
<span class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></span>
<span class='title'>
<span class='floatleft' macro='tiddlerIcons' style='cursor:auto !important;'></span>
<span macro='view title'></span>
</span>
<span class='subtitle'>
<span style='white-space:nowrap' macro='view modified date [[DDD, MMM DDth YYYY]]'></span>
</span>
<div class='tagClear'></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<!-- TASK CONTROLS one line hanging "bubble" (bottom right) -->
<div class='viewer'>
<div macro='view text wikified'></div>
<div class="floatright block" style="height:2em;padding-top:2px;">
<div class="center viewer smallform" style="padding:.5em 1em">
<span class='fine subtitle'>task status:</span>
<span macro='select status rows:1 allowOther "not started" "in progress" "on hold" "completed"'></span>
<span class='fine subtitle'>assigned to:</span>
<span macro='select assigned rows:1 allowBlank allowOther +TaskAssignmentList allowEdit'></span>
<span macro='checkbox urgent@'></span>
<span class='fine subtitle'>urgent</span>
<span macro='taskTimer'></span>
<span class='fine subtitle' style='padding-left:1em'
macro='wikify [[+++^40em^{{small{[add a note]}}}...<<moveablePanel>>add a note<html><hr></html><<comment here "" "+++!!!!![%when% (%who%): %subject%]>...\n%message%\n===\n">>=== | <<tiddler ExpandSlidersScript with: here "view all" "close all">>]]'></span>
</div>
</div>
</div>
<div class='tagClear'></div>
<!--}}}-->
<<clock2 chunkySwiss>> <html><font size=4><b>W</b></font></html>elcome. Ever heard the saying ''//You can't manage what you can't measure//''?
Managing your __time__ (actually managing //yourself//) matters because, as [[Randy Pausch|http://en.wikipedia.org/wiki/Randy_Pausch]] put it:
>''//Managing your time well makes you successful.//'' You don't become successful, //then// find time manage to your time well.
But how?
<<<
//...all effective people work on their time management perpetually. They... ''keep a continuing log and analyze it periodically''...// Peter Drucker.
<<<
Do you log your time now? Do you ''know'' where it goes (or do you just //think// you do)? If you haven't done so, you should keep a @@time journal@@, at least for a while; then you will __know__. ''~TiddlyTimeJournal'' (TTJ) is a small, intentionally simple but adequate, application to help you do this. It's contained in a single HTML document and is an example of a ''[[TiddlyWiki|http://www.tiddlywiki.com]]'' -- a file you can conveniently keep on a USB memory stick on your key ring. All you need to run this application is a web browser. You are welcome to copy it and share it.
Start here: [[GettingStarted]], [[Instructions]] and, //fyi//, [[Background]].
Right click <<linkToMe 'here'>> and select @@color(blue):Save Link As@@ to download your own copy of TTJ.
----
This ~TimeJournal lists the contents of all tiddlers tagged with the word "task" (//i.e.//,those created by the task timer). To have another report included in this listing, //e.g.//, the contents of a tiddler named EventLog, just tag it with the word ''task''.
Click [[here|TimeJournalExport]] to generate a TimeJournal report file (''C:\~TimeJournal.txt'' will be created; you must be able to write to this location). Otherwise print or cut and paste from this screen.
<<forEachTiddler
where
'tiddler.tags.contains("task")'
write
'"<html><B><font size =3>"+ tiddler.title+ "</b></font></html>" + "----\n<<tiddler [["+tiddler.title+"]]$))\n"'
>>
The following macro call exports all tiddlers tagged with ''task'' to a text file "c:/TimeJournal.txt", using a customized format.
Source: http://tiddlywiki.abego-software.de/#ForEachTiddlerExamples
{{{
<<forEachTiddler
script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "==== "+tiddler.title+"=========================\nTags: "+ getSortedTagsText(tiddler)+"\nModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\nModifier: "+tiddler.modifier+"\n--------------------------------------------------\n"+tiddler.text+"\n--------------------------------------------------\n(End of "+tiddler.title+")\n\n\n\n"}'
write
'writeTiddler(tiddler)'
toFile 'file:///c:/mywallet.txt' withLineSeparator '\r\n'
>>
}}}
For better readablility here the script text in a nicer layout:
{{{
function getSortedTagsText(tiddler) {
var tags = tiddler.tags;
if (!tags)
return "";
tags.sort();
var result = "";
for (var i = 0; i < tags.length;i++) {
result += tags[i]+ " ";
}
return result;
}
function writeTiddler(tiddler) {
return "====[ "+tiddler.title+" ]=========================\n"+
"Tags: "+ getSortedTagsText(tiddler)+"\n"+
"Modified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\n"+
"Modifier: "+tiddler.modifier+"\n"+
"--------------------------------------------------\n"+
tiddler.text+"\n"+
"--------------------------------------------------\n"
"(End of "+tiddler.title+")\n\n\n\n"
}
}}}
<<forEachTiddler
where
'tiddler.tags.contains("task")'
script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "====[ "+tiddler.title+" ]=========================\nTags: "+ getSortedTagsText(tiddler)+"\nModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\nModifier: "+tiddler.modifier+"\n--------------------------------------------------\n"+tiddler.text+"\n--------------------------------------------------\n(End of "+tiddler.title+")\n\n\n\n"}'
write
'writeTiddler(tiddler)'
toFile 'file:///c:/TimeJournal.txt' withLineSeparator '\r\n'
>>
<html><font size=4><b>Away from a computer</b></font></html>
I use [[TikTok|http://www.freewarepalm.com/clock/tiktok.shtml]] on a Treo 650, but only when I feel I need to. It's a fine little application. It's free. Have you ever wanted to relieve the boredeom of a dull meeting? ~TikTok allows you to record the total time for which individuals speak (or drone, as the case may be) with a few stylus taps on the screen; just enter people's names instead of those of activities or projects.
<html><font size=4><b>You May Also Like</b></font></html>
* [[TiddlyFolio|http://www.tiddlywiki.org/wiki/TiddlyFolio]], a ~TiddlyWiki application for keeping track (securely) of the contents of your wallet (debit and credit cards, membership numbers etc.) and your passwords.
* [[YourTimesheets|http://www.yourtimesheets.com]], a ~TiddlyWiki timesheet application; useful if you are mainly concerned to account for overall hours worked and as demonstration of the flexibility of ~TiddlyWiki.
<html><font size=4><b>My Preferred Tool</b></font></html>
For keeping track of tasks and priorities on a PC is [[MyLifeOrganized|http://www.mylifeorganized.net]], a version of which is available for free. It's a Windows application that can run from a thumb drive, under [[WINE|http://www.winehq.org/]] on Linux, and via [[Crossover|http://www.codeweavers.com/products/cxmac/]] on a Mac.
Disclaimer: I am a satisfied user, nothing else.
''Personal reflection:'' Successful time management is a journey not a destination (just because it's a cliche doesn't mean it isn't true). I have found a few useful things along the way, such //Getting Things Done// by David Allen (Google ''GTD'' if this is new to you), but the number 1 lesson is not to become too preoccupied with efficiency and perfection. There isn't time to evaluate every tool or read about every productivity hack.
/***
|Name|ToggleSideBarMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#ToggleSideBarMacro|
|Version|1.0|
|Requires|~TW2.x|
!Description:
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.
!Demo
<<toggleSideBar "Toggle Sidebar">>
!Usage:
{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)
You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}
!History
*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour.
*20-07-06: version 0.11
*27-04-06: version 0.1: working.
!Code
***/
//{{{
config.macros.toggleSideBar={};
config.macros.toggleSideBar.settings={
styleHide : "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
styleShow : " ",
arrow1: "«",
arrow2: "»"
};
config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
{
var tooltip= params[1]||'toggle sidebar';
var mode = (params[2] && params[2]=="hide")? "hide":"show";
var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
var label= (params[0]&¶ms[0]!='.')?params[0]+" "+arrow:arrow;
var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
if (mode == "hide")
{
(document.getElementById("sidebar")).setAttribute("toggle","hide");
setStylesheet(this.settings.styleHide,"ToggleSideBarStyles");
}
};
config.macros.toggleSideBar.onToggleSideBar = function(){
var sidebar = document.getElementById("sidebar");
var settings = config.macros.toggleSideBar.settings;
if (sidebar.getAttribute("toggle")=='hide')
{
setStylesheet(settings.styleShow,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","show");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);
}
else
{
setStylesheet(settings.styleHide,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","hide");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);
}
return false;
}
setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");
//}}}
# Keep a time journal!
# Check [[here|http://www.google.co.uk/search?hl=en&q=top+time+management+tips&btnG=Search&meta=]] (Google) now and then; Schedule some some time for this; see nr 3. (//Sharpen the saw.// Stephen Covey)
# If you're a perfectionist: learn [[time boxing|http://www.google.co.uk/search?hl=en&q=time+boxing&btnG=Google+Search&meta=]]
#
#
#
#
#
#
#
I will add to this list with each update of ~TiddlyTimeJournal.
If you have a tip or a link you'd like to see here send me an email (see [[About]] for my email address).