Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
Date: 2009-04-19
Item: BasilFamousBrandSweet
Germ: 0423
Yield: ?
Comments: Transplanted 5/24. New jiffy peats don't fit in jiffy container
Germ: 7
Yield: 90
Thin: 12in
Yield is a guess -- nothing on package.
Date: 2009-04-12
Item: BeanFamousBrandFighter
Germ: 0421
Yield: ?
Comments: On front strawberry row -- 2/3rds west side. These were seeds from 2007.
Date: 2009-05-06
Item: BeanFamousBrandTenderpod
Germ: ?
Yield: ?
Comments:
Germ: 7
Thin: 6
Yield: 55
Germ: 7
Yield: 50
Thin: 6 in
Very tender, excellent flavor, pods 5.25 long. Sow in avg soil in full sun.
Date: 2009-04-27
Item: BeetDetroitAdequate
Germ: 0510
Yield: ?
Comments: First 1/2 row on far east side of North Garden
Yield: 59
Germ: 14
Thin: 3" when 1"
* Germ in 14 to 21 days
Comments:
Hybrid Royal Marvel, 75722,
Yield: 120
Germ: 4
Germ in 4 to 10 days
Comments: Prefer cool, moist soil
Thin: 4 in
Date: 2009-04-05
Item: CantalopeNational
Germ: 0418
Yield: ?
Comments: 2008 seeds. In green house
Germ: 7
Germ in 7 to 14 days
Yield: 90
Comments: Sunny locations. Thin to 3/4 plants per hill.
Germ: 10
Yield: 65
* Germ 10 - 17 days
Thin: 2-4 in
* 14328
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Documentation
>see [[CheckboxPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)". Also, wrap handlers in "function()" so "return" can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
//}}}
//{{{
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
name: "checkbox",
match: "\\[[xX_ ][\\]\\=\\(\\{]",
lookahead: "\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
// get params
var checked=(lookaheadMatch[1].toUpperCase()=="X");
var id=lookaheadMatch[2];
var target=lookaheadMatch[3];
if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
var fn_init=lookaheadMatch[4];
var fn_clickBefore=lookaheadMatch[5];
var fn_clickAfter=lookaheadMatch[6];
var tid=story.findContainingTiddler(w.output); if (tid) tid=tid.getAttribute("tiddler");
var srctid=w.tiddler?w.tiddler.title:null;
config.macros.checkbox.create(w.output,tid,srctid,w.matchStart+1,checked,id,target,config.checkbox.refresh,fn_init,fn_clickBefore,fn_clickAfter);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} );
config.macros.checkbox = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
if(!(tiddler instanceof Tiddler)) { // if no tiddler passed in try to find one
var here=story.findContainingTiddler(place);
if (here) tiddler=store.getTiddler(here.getAttribute("tiddler"))
}
var srcpos=0; // "inline X" not applicable to macro syntax
var target=params.shift(); if (!target) target="";
var defaultState=params[0]=="checked"; if (defaultState) params.shift();
var id=params.shift(); if (id && !id.length) id=null;
var fn_init=params.shift(); if (fn_init && !fn_init.length) fn_init=null;
var fn_clickBefore=params.shift();
if (fn_clickBefore && !fn_clickBefore.length) fn_clickBefore=null;
var fn_clickAfter=params.shift();
if (fn_clickAfter && !fn_clickAfter.length) fn_clickAfter=null;
var refresh={ tagged:true, tagging:true, container:false };
this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter);
},
create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
// create checkbox element
var c = document.createElement("input");
c.setAttribute("type","checkbox");
c.onclick=this.onClickCheckbox;
c.srctid=srctid; // remember source tiddler
c.srcpos=srcpos; // remember location of "X"
c.container=tid; // containing tiddler (may be null if not in a tiddler)
c.tiddler=tid; // default target tiddler
c.refresh = {};
c.refresh.container = refresh.container;
c.refresh.tagged = refresh.tagged;
c.refresh.tagging = refresh.tagging;
place.appendChild(c);
// set default state
c.checked=defaultState;
// track state in config.options.ID
if (id) {
c.id=id.substr(1); // trim off leading "="
if (config.options[c.id]!=undefined)
c.checked=config.options[c.id];
else
config.options[c.id]=c.checked;
}
// track state in (tiddlername|tagname) or (fieldname@tiddlername)
if (target) {
var pos=target.indexOf("@");
if (pos!=-1) {
c.field=pos?target.substr(0,pos):"checked"; // get fieldname (or use default "checked")
c.tiddler=target.substr(pos+1); // get specified tiddler name (if any)
if (!c.tiddler || !c.tiddler.length) c.tiddler=tid; // if tiddler not specified, default == container
if (store.getValue(c.tiddler,c.field)!=undefined)
c.checked=(store.getValue(c.tiddler,c.field)=="true"); // set checkbox from saved state
} else {
var pos=target.indexOf("|"); if (pos==-1) var pos=target.indexOf(":");
c.tag=target;
if (pos==0) c.tag=target.substr(1); // trim leading "|" or ":"
if (pos>0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
if (!c.tag.length) c.tag="checked";
var t=store.getTiddler(c.tiddler);
if (t && t.tags)
c.checked=t.isTagged(c.tag); // set checkbox from saved state
}
}
// trim off surrounding { and } delimiters from init/click handlers
if (fn_init) c.fn_init="(function(){"+fn_init.trim().substr(1,fn_init.length-2)+"})()";
if (fn_clickBefore) c.fn_clickBefore="(function(){"+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+"})()";
if (fn_clickAfter) c.fn_clickAfter="(function(){"+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+"})()";
c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
},
onClickCheckbox: function(event) {
window.place=this;
if (this.init && this.fn_init) // custom function hook to set initial state (run only once)
{ try { eval(this.fn_init); } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
if (!this.init && this.fn_clickBefore) // custom function hook to override changes in checkbox state
{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage("Checkbox onClickBefore error: "+e.toString()); } }
if (this.id)
// save state in config AND cookie (only when ID starts with 'chk')
{ config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }
if (this.srctid && this.srcpos>0 && (!this.id || this.id.substr(0,3)!="chk") && !this.tag && !this.field) {
// save state in tiddler content only if not using cookie, tag or field tracking
var t=store.getTiddler(this.srctid); // put X in original source tiddler (if any)
if (t && this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed
t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);
if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
store.setDirty(true);
}
}
if (this.field) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
// set the field value in the target tiddler
store.setValue(this.tiddler,this.field,this.checked?"true":"false");
// DEBUG: displayMessage(this.field+"@"+this.tiddler+" is "+this.checked);
}
if (this.tag) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
var t=store.getTiddler(this.tiddler);
if (t) {
var tagged=(t.tags && t.tags.indexOf(this.tag)!=-1);
if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
if (!this.checked && tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
}
// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
if (this.checked!=tagged) {
if (this.refresh.tagged) {
if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
story.refreshTiddler(this.tiddler,null,true);
else // the TAGGED tiddler in edit mode (with tags field)
config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked);
}
if (this.refresh.tagging)
if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
}
}
if (!this.init && this.fn_clickAfter) // custom function hook to react to changes in checkbox state
{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage("Checkbox onClickAfter error: "+e.toString()); } }
// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
if (!this.init && this.refresh.container && this.container!=this.tiddler)
if (!story.isDirty(this.container)) story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox
return true;
},
refreshEditorTagField: function(title,tag,set) {
var tagfield=story.getTiddlerField(title,"tags");
if (!tagfield||tagfield.getAttribute("edit")!="tags") return; // if no tags field in editor (i.e., custom template)
var tags=tagfield.value.readBracketedList();
if (tags.contains(tag)==set) return; // if no change needed
if (set) tags.push(tag); // add tag
else tags.splice(tags.indexOf(tag),1); // remove tag
for (var t=0;t<tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
tagfield.value=tags.join(" "); // reassemble tag string (with brackets as needed)
return;
}
}
//}}}
|Name|CheckboxPluginInfo|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|documentation for CheckboxPlugin|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* setting/removing tags on specified tiddlers,
* or, setting custom field values on specified tiddlers,
* or, saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler source content (deprecated).
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Inline (wiki syntax) Usage
<<<
//{{{
[ ]or[_] and [x]or[X]
//}}}
Simple checkboxes using 'Inline X' storage. The current unchecked/checked state is indicated by the character between the {{{[}}} and {{{]}}} brackets ("_" means unchecked, "X" means checked). When you click on a checkbox, the current state is retained by directly modifying the tiddler content to place the corresponding "_" or "X" character in between the brackets.
>//''NOTE: 'Inline X' syntax has been deprecated...'' This storage format only works properly for checkboxes that are directly embedded and accessed from content in a single tiddler. However, if that tiddler is 'transcluded' into another (by using the {{{<<tiddler TiddlerName>>}}} macro), the 'Inline X' will be ''erroneously stored in the containing tiddler's source content, resulting in corrupted content in that tiddler.'' For anything but the most simple of "to do list" uses, you should select from the various alternative storage methods described below...//
//{{{
[x=id]
//}}}
Assign an optional ID to the checkbox so you can use {{{document.getElementByID("id")}}} to manipulate the checkbox DOM element, as well as tracking the current checkbox state in {{{config.options["id"]}}}. If the ID starts with "chk" the checkbox state will also be saved in a cookie, so it can be automatically restored whenever the checkbox is re-rendered (overrides any default {{{[x]}}} or {{{[_]}}} value). If a cookie value is kept, the "_" or "X" character in the tiddler content remains unchanged, and is only applied as the default when a cookie-based value is not currently defined.
//{{{
[x(title|tag)] or [x(title:tag)]
//}}}
Initializes and tracks the current checkbox state by setting or removing a particular tag value from a specified tiddler. If you omit the tiddler title (and the | or : separator), the specified tag is assigned to the current tiddler. If you omit the tag value, as in {{{(title|)}}}, the default tag, {{{checked}}}, is assumed. Omitting both the title and tag, {{{()}}}, tracks the checkbox state by setting the "checked" tag on the current tiddler. When tag tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If a tiddler title named in the tag does not exist, the checkbox state defaults to the "inline X" value. If this value is //checked//, or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the tag to it. //''NOTE: beginning with version 2.1.2 of this plugin, the "|" separator is the preferred separator between the title and tag name, as it avoids syntactic ambiguity when ":" is used within tiddler titles or tag names.''//
//{{{
[x(field@tiddler)]
//}}}
Initializes and tracks the current checkbox state by setting a particular custom field value from a specified tiddler. If you omit the tiddler title (but not the "@" separator), the specified field on the current tiddler is used. If you omit the field name, as in {{{(@tiddler)}}}, a default fieldname of {{{checked}}} is assumed. Omitting both the field and the tiddler title, {{{(@)}}}, defaults to setting the "checked" field on the current tiddler. When field tracking is used, the "_" or "X" character in the tiddler content remains unchanged, and is not used to set or track the checkbox state. If the tiddler title named in the parameter does not exist, the checkbox state defaults to the "inline X" value. If this value is //checked// or is subsequently changed to //checked//, it will automatically create the missing tiddler and then add the field to it.
//{{{
[x{javascript}{javascript}{javascript}]
//}}}
You can define optional javascript code segments to add custom initialization and/or 'onClick' handlers to a checkbox. The current checkbox state (and it's other DOM attributes) can be set or read from within these code segments by reference to a globally-defined context object, "place" (which can also be referenced as "window.place").
The first code segment will be executed when the checkbox is initially displayed, so that you can programmatically determine it's starting checked/unchecked state. The second code segment (if present) is executed whenever the checkbox is clicked, but //before the regular checkbox processing in performed// ("onClickBefore"), so that you can apply programmed responses or intercept and override the checkbox state based on custom logic. The third code segment (if present) is executed whenver the checkbox is clicked, //after the regular checkbox processing has completed// ("onClickAfter"), so that you can include "side-effect" processing based on the checkbox state just applied.
>Note: if you want to use the default checkbox initialization processing with a custom onClickBefore/After function, use this syntax:
>{{{[x(tag){}{javascript}]}}} or {{{[x(tag){}{}{javascript}]}}}
<<<
!!!!!Macro usage
<<<
In addition to embedded checkboxes using the wiki syntax described above, a ''macro-based syntax'' is also provided, for use in templates where wiki syntax cannot be directly used. This macro syntax can also be used in tiddler content, as an alternative to the wiki syntax. When embedded in [[PageTemplate]], [[ViewTemplate]], or [[EditTemplate]] (or custom alternative templates), use the following macro syntax:
//{{{
<span macro="checkbox target checked id onInit onClickBefore onClickAfter"></span>
//}}}
or, when embedded in tiddler content, use the following macro syntax:
//{{{
<<checkbox target checked id onInit onClickBefore onClickAfter>>
//}}}
where:
''target''
>is either a tag reference (e.g., ''tagname|tiddlername'') or a field reference (e.g. ''fieldname@tiddlername''), as described above.
''checked'' (optional)
>is a keyword that sets the initial state of the checkbox to "checked". When omitted, the default checkbox state is "unchecked".
''id'' (optional)
>specifies an internal config.options.* ID, as described above. If the ID begins with "chk", a cookie-based persistent value will be created to track the checkbox state in between sessions.
''onInit'' (optional)
>contains a javascript event handler to be performed when the checkbox is initially rendered (see details above).
''onClickBefore'' and/or ''onClickAfter'' (optional)
>contains a javascript event handler to be performed each time the checkbox is clicked (see details above). //note: to use the default onInit handler with a custom onClickBefore/After handler, use "" (empty quotes) or {} (empty function) as a placeholder for the onInit and/or onClickBefore parameters//
<<<
!!!!!Examples
<<<
''checked and unchecked static default ("inline X") values:''
//{{{
[X] label
[_] label
//}}}
>[X] label
>[_] label
''document-based value (id='demo', no cookie):''
//{{{
[_=demo] label
//}}}
>[_=demo] label
''cookie-based value (id='chkDemo'):''
//{{{
[_=chkDemo] label
//}}}
>[_=chkDemo] label
''tag-based value (TogglyTagging):''
//{{{
[_(CheckboxPluginInfo|demotag)]
[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}]
//}}}
>[_(CheckboxPluginInfo|demotag)] toggle 'demotag' (and refresh tiddler display)
>[_(CheckboxPluginInfo|demotag){place.refresh.tagged=place.refresh.container=false}] toggle 'demotag' (no refresh)
''field-based values:''
//{{{
[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
[_(demofield@)] demofield@ (equivalent to demonfield@ current tiddler)
[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
[_(@)] @ (equivalent to checked@ current tiddler)
//}}}
>[_(demofield@CheckboxPluginInfo)] demofield@CheckboxPluginInfo
>[_(demofield@)] demofield@ (current tiddler)
>[_(checked@CheckboxPluginInfo)] checked@CheckboxPluginInfo
>[_(@CheckboxPluginInfo)] @CheckboxPluginInfo
>[_(@)] toggle field: @ (defaults to "checked@here")
>click to view current: <<toolbar fields>>
''custom init and onClick functions:''
//{{{
[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
//}}}
>[X{place.checked=true}{alert(place.checked?"on":"off")}] message box with checkbox state
''retrieving option values:''
>config.options['demo']=<script>return config.options['demo']?"true":"false";</script>
>config.options['chkDemo']=<script>return config.options['chkDemo']?"true":"false";</script>
<<<
!!!!!Configuration
<<<
Normally, when a checkbox state is changed, the affected tiddlers are automatically re-rendered, so that any checkbox-dependent dynamic content can be updated. There are three possible tiddlers to be re-rendered, depending upon where the checkbox is placed, and what kind of storage method it is using.
*''container'': the tiddler in which the checkbox is displayed. (e.g., this tiddler)
*''tagged'': the tiddler that is being tagged (e.g., "~MyTask" when tagging "~MyTask:done")
*''tagging'': the "tag tiddler" (e.g., "~done" when tagging "~MyTask:done")
You can set the default refresh handling for all checkboxes in your document by using the following javascript syntax either in a systemConfig plugin, or as an inline script. (Substitute true/false values as desired):
{{{config.checkbox.refresh = { tagged:true, tagging:true, container:true };}}}
You can also override these defaults for any given checkbox by using an initialization function to set one or more of the refresh options. For example:
{{{[_{place.refresh.container=false}]}}}
<<<
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)". Also, wrap handlers in "function()" so "return" can be used within handler code.
2008.01.02 [2.3.0] split optional custom onClick handling into separate onClickBefore and onClickAfter handlers. The onClickBefore handler permits interception of the click BEFORE the checkbox is set. onClickAfter allows follow-on 'side-effect' processing to occur AFTER the checkbox is set.
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.08.06 [2.2.5] supress automatic refresh of any tiddler that is currently being edited. Ensures that current tiddler edit sessions are not prematurely discarded (losing any changes). However, if checkbox changes a tag on a tiddler being edited, update the "tags" input field (if any) so that saving the edited tiddler correctly reflects any changes due to checkbox activity... see refreshEditorTagField().
2007.07.13 - 2.2.4 in handler(), fix srctid reference (was "w.tiddler", should have been "w.tiddler.title"). This fixes broken 'inline X' plus fatal macro error when using PartTiddlerPlugin. Thanks to cmari for reporting the problem and UdoBorkowski for finding the code error.
2007.06.21 - 2.2.3 suppress automatic refresh of tiddler when using macro-syntax to prevent premature end of tiddler editing session.
2007.06.20 - 2.2.2 fixed handling for 'inline X' when checkboxes are contained in a 'trancluded' tiddler. Now, regardless of where an inline X checkbox appears, the X will be placed in the originating source tiddler, rather than the tiddler in which the checkbox appears.
2007.06.17 - 2.2.1 Refactored code to add checkbox //macro// syntax for use in templates (e.g., {{{macro="checkbox ..."}}}. Also, code cleanup of existing tag handling.
2007.06.16 - 2.2.0 added support for tracking checkbox states using tiddler fields via "(fieldname@tiddlername)" syntax.
2006.05.04 - 2.1.3 fix use of findContainingTiddler() to check for a non-null return value, so that checkboxes won't crash when used outside of tiddler display context (such as in header, sidebar or mainmenu)
2006.03.11 - 2.1.2 added "|" as delimiter to tag-based storage syntax (e.g. "tiddler|tag") to avoid parsing ambiguity when tiddler titles or tag names contain ":". Using ":" as a delimiter is still supported but is deprecated in favor of the new "|" usage. Based on a problem reported by JeffMason.
2006.02.25 - 2.1.0 added configuration options to enable/disable forced refresh of tiddlers when toggling tags
2006.02.23 - 2.0.4 when toggling tags, force refresh of the tiddler containing the checkbox.
2006.02.23 - 2.0.3 when toggling tags, force refresh of the 'tagged tiddler' so that tag-related tiddler content (such as "to-do" lists) can be re-rendered.
2006.02.23 - 2.0.2 when using tag-based storage, allow use [[ and ]] to quote tiddler or tag names that contain spaces:
{{{[x([[Tiddler with spaces]]:[[tag with spaces]])]}}}
2006.01.10 - 2.0.1 when toggling tags, force refresh of the 'tagging tiddler'. For example, if you toggle the "systemConfig" tag on a plugin, the corresponding "systemConfig" TIDDLER will be automatically refreshed (if currently displayed), so that the 'tagged' list in that tiddler will remain up-to-date.
2006.01.04 - 2.0.0 update for ~TW2.0
2005.12.27 - 1.1.2 Fix lookAhead regExp handling for {{{[x=id]}}}, which had been including the "]" in the extracted ID.
Added check for "chk" prefix on ID before calling saveOptionCookie()
2005.12.26 - 1.1.2 Corrected use of toUpperCase() in tiddler re-write code when comparing {{{[X]}}} in tiddler content with checkbox state. Fixes a problem where simple checkboxes could be set, but never cleared.
2005.12.26 - 1.1.0 Revise syntax so all optional parameters are included INSIDE the [ and ] brackets. Backward compatibility with older syntax is supported, so content changes are not required when upgrading to the current version of this plugin. Based on a suggestion by GeoffSlocock
2005.12.25 - 1.0.0 added support for tracking checkbox state using tags ("TogglyTagging")
Revised version number for official post-beta release.
2005.12.08 - 0.9.3 support separate 'init' and 'onclick' function definitions.
2005.12.08 - 0.9.2 clean up lookahead pattern
2005.12.07 - 0.9.1 only update tiddler source content if checkbox state is actually different. Eliminates unnecessary tiddler changes (and 'unsaved changes' warnings)
2005.12.07 - 0.9.0 initial BETA release
<<<
<script label="Compile Story">
//{{{
// This script should not be run from a tiddler that is
// part of the story!
var first = true;
var summaryTitle = "AccidentalTitle" ; // Need more scripting to protect against empty story
var who, when, out,tags,fields, summaryElement ;
story.forEachTiddler(function(title,ele) {
//tid = story.findContainingTiddler(tid) ;
tid = store.getTiddler(title) ;
if(first) {
//var tid=store.getTiddler(t);
summaryTitle = title ;
summaryElement = ele ;
var who=tid?tid.modifier:config.options.txtUserName;
var when=tid?tid.modified:new Date();
out=tid?tid.text:'' ;
var tags=tid?tid.tags:[];
var fields=tid?tid.fields:{};
first = false ;
} else {
out+=tid.text ;
store.removeTiddler(title) ;
story.closeTiddler(title) ;
}
/*-- FOR LATER get new tags and add to existing tags (if any) */
//var newtags=curTiddler.tagsfield.value.readBracketedList();
//for (var i=0; i<newtags.length; i++) tags.pushUnique(newtags[i]);
} ) ; // foreach
/* write and show tiddler */
store.saveTiddler(summaryTitle,summaryTitle,out, who, when, tags, fields);
story.refreshAllTiddlers(true) ;
//story.displayTiddler(story.findContainingTiddler(summaryElement),summaryTitle);
//}}}
</script>
<script>
function tempstuff(place) {
var str = "" ;
var weekDayList = new Array("Mo","Tu","We","Th","Fr","Sa","Su") ;
var monthStartList = {
0 : [ 3 , "''Ja'' | ''0''" ],
1 : [ 6 , "''Fe'' | ''31''" ],
2 : [ 6 , "''Mr'' | ''59''" ],
3 : [ 2 , "''Ap'' | ''90''" ],
4 : [ 4 , "''My'' | ''120''" ],
5 : [ 0 , "''Jn'' | ''151''" ],
6 : [ 2 , "''Jl'' | ''181''" ],
7 : [ 5 , "''Au'' | ''212''" ],
8 : [ 1 , "''Se'' | ''243''" ],
9 : [ 3 , "''Oc'' | ''273''" ],
10 : [ 6 , "''No'' | ''304''" ],
11 : [ 1 , "''De'' | ''334''" ]
} ;
//var monthStartList = {
// 0 : [ 3 , "''Ja Oct''" ],
// 1 : [ 6 , "''F Mr N''" ],
// 2 : [ 2 , "''Ap Jl''" ],
// 3 : [ 4 , "''May''" ],
// 4 : [ 0 , "''Jun''" ],
// 5 : [ 5 , "''Aug''" ],
// 6 : [ 1 , "''Se De''" ]
//
//}
str = "" ;
for(var j=0;j<12;j++) {
str += "|" ;
for(var i=0;i<weekDayList.length;i++) {
str += weekDayList[(i+ monthStartList[j][0])%7] +"|" ;
}
str += monthStartList[j][1] + "|" ;
str += "\n" ;
}
for(var i=0;i<32;i++) {
switch(i) {
case 0 :
str += "|" ;
break ;
case 7 :
case 14 :
case 21 :
str += " " + i + " | |\n|" ;
break ;
case 28 :
str += " ''28'' ||\n|" ;
break ;
//case 29 :
//str += " ''29'' |>|>|>|>|>|>|''Feb 2012''|\n" ;
//break ;
case 30 :
// str += "''30''|''Apr Jun Sep Nov'' |>|>|>|>|>|\n" ;
str += "''30'' |" ;
break ;
case 31 :
//str += "|| |''31''|''Jan Mar May Jul Aug Oct Dec'' |>|>|>|>|\n" ;
str += " ''31''| |>|>|>|>|\n" ;
break ;
default :
str += " " + i + " |" ;
}
}
//str += "@@font-size:x-small;\n" +
//"|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|\n" +
//"|31|59|90|120|151|181|212|243|273|304|334|\n@@" ;
wikify(str,place) ;
//document.write(str) ;
//return "test" ;
}
tempstuff(place) ;
</script>
Date: 2009-04-10
Item: SpecialtyNameBrandCorn
Germ: 0423
Yield: ?
Comments: Row East part of S. garden
Date: 2009-05-24
Item: SpecialtyNameBrandCorn
Germ: ?
Yield: ?
Comments: Half row far east side of south garden.
Date: 2009-04-27
Item: SpecialtyNameBrandCorn
GermETA: 0507
YieldETA: 0714
Germ: 0502
Yield: ?
Comments: Started 12 in jiffy set. Planted 5/2.
Date: 2009-04-16
Item: CucumberFamousBrandBush
Germ: 0421
Yield: ?
Comments: Transferred 4/23. Start In green house
Date: 2009-04-16
Item: CucumberFamousBrandSugar
Germ: 0421
Yield: ?
Comments: Transferred 4/23. Start In green house
Germ: 7
Yield: 55
Thin: 2-3 per hill when 2-3" high
Comments: Mosaic resistant
* Germ in 7 -14 days
Germ: 7
Yield: 57
Thin: 2-3 plants when 2-3 in
Germ in 7 - 14 days.
Comments: Plant 4 to 6 per hill. Snack size cucumber
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).
Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers.
''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.
''Access and Modify Tiddler Data''
You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields.
These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//
''Data Representation in a Tiddler''
The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]].
//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}
The data section is not displayed when viewing the tiddler (see also "The showData Macro").
Beside the data section a tiddler may have all kind of other content.
Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.
''Saving Changes''
The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.
''Notifications''
No notifications are sent when a tiddler's data value is changed through the "setData" methods.
''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.
''The showData Macro''
By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:
''Syntax:''
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
!Revision history
* v1.0.6 (2006-08-26)
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed:
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features:
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed:
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// DataTiddlerPlugin
//============================================================================
//============================================================================
// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {
version.extensions.DataTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006, 7, 26),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) {
TiddlyWiki.prototype.getTiddler = function(title) {
var t = this.tiddlers[title];
return (t !== undefined && t instanceof Tiddler) ? t : null;
};
}
//============================================================================
// DataTiddler Class
//============================================================================
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
function DataTiddler() {
}
DataTiddler = {
// Function to stringify a JavaScript value, producing the text for the data section content.
// (Must match the implementation of DataTiddler.parse.)
//
stringify : null,
// Function to parse the text for the data section content, producing a JavaScript value.
// (Must match the implementation of DataTiddler.stringify.)
//
parse : null
};
// Ensure access for IE
window.DataTiddler = DataTiddler;
// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------
// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};
// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler+ "("+t+")";
}
DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};
// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...)
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataObject(t);
};
// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.readDataSectionText(t);
};
// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------
// Internal.
//
// The original JSONError is not very user friendly,
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
if (ex.name == 'JSONError') {
ex.toString = function() {
return ex.name + ": "+ex.message+" ("+ex.text+")";
};
}
return ex;
};
// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
if (t.dataObject === undefined) {
var data = DataTiddler.readData(t);
t.dataObject = (data) ? data : {};
}
return t.dataObject;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
return (value === undefined) ? defaultValue : value;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
var oldValue = data[field];
if (value == defaultValue) {
if (oldValue !== undefined) {
delete data[field];
DataTiddler.save(tiddler);
}
return;
}
data[field] = value;
DataTiddler.save(tiddler);
};
// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
if (matches === null || !matches[2]) {
return null;
}
return matches[2];
};
// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
var text = DataTiddler.readDataSectionText(tiddler);
try {
return text ? DataTiddler.parse(text) : null;
} catch(ex) {
throw DataTiddler.extendJSONError(ex);
}
};
// Internal.
//
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
return DataTiddler.stringify(data);
};
// Internal.
//
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
var index = s.indexOf(subString, startIndex);
while ((index > 0) && (s[index-1] == '~')) {
index = s.indexOf(subString, index+1);
}
return index;
};
// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
// Special care must be taken to handle "<data>" and "</data>" texts inside
// a data section.
// Also take care not to use an escaped <data> (i.e. "~<data>") as the start
// of a data section. (Same for </data>)
// NOTE: we are explicitly searching for a data section that contains a JSON
// string, i.e. framed with braces. This way we are little bit more robust in
// case the tiddler contains unescaped texts "<data>" or "</data>". This must
// be changed when using a different stringifier.
var startTagText = "<data>{";
var endTagText = "}</data>";
var startPos = 0;
// Find the first not escaped "<data>".
var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
if (startDataTagIndex < 0) {
return null;
}
// Find the *last* not escaped "</data>".
var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
if (endDataTagIndex < 0) {
return null;
}
var nextEndDataTagIndex;
while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
endDataTagIndex = nextEndDataTagIndex;
}
return {
prefixEnd: startDataTagIndex,
dataStart: startDataTagIndex+(startTagText.length)-1,
dataEnd: endDataTagIndex,
suffixStart: endDataTagIndex+(endTagText.length)
};
};
// Internal.
//
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
var text = tiddler.text;
var info = DataTiddler.getDataSectionInfo(text);
if (!info) {
return null;
}
var prefix = text.substr(0,info.prefixEnd);
var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
var suffix = text.substr(info.suffixStart);
return [text, prefix, data, suffix];
};
// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change).
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected.
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send.
//
// This method should only be called when the data really has changed.
//
// @param tiddler
// the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
var prefix;
var suffix;
if (matches === null) {
prefix = tiddler.text;
suffix = "";
} else {
prefix = matches[1];
suffix = matches[3];
}
var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
var newText =
(dataText !== null)
? prefix + "<data>" + dataText + "</data>" + suffix
: prefix + suffix;
if (newText != tiddler.text) {
// make the change in the tiddlers text
// ... see DataTiddler.MyTiddlerChangedFunction
tiddler.isDataTiddlerChange = true;
// ... do the action change
tiddler.set(
tiddler.title,
newText,
config.options.txtUserName,
config.options.chkForceMinorUpdate? undefined : new Date(),
tiddler.tags);
// ... see DataTiddler.MyTiddlerChangedFunction
delete tiddler.isDataTiddlerChange;
// Mark the store as dirty.
store.dirty = true;
// AutoSave if option is selected
if(config.options.chkAutoSave) {
saveChanges();
}
}
};
// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
// Remove the data object from the tiddler when the tiddler is changed
// by code other than DataTiddler code.
//
// This is necessary since the data object is just a "cached version"
// of the data defined in the data section of the tiddler and the
// "external" change may have changed the content of the data section.
// Thus we are not sure if the data object reflects the data section
// contents.
//
// By deleting the data object we ensure that the data object is
// reconstructed the next time it is needed, with the data defined by
// the data section in the tiddler's text.
// To indicate that a change is a "DataTiddler change" a temporary
// property "isDataTiddlerChange" is added to the tiddler.
if (this.dataObject && !this.isDataTiddlerChange) {
delete this.dataObject;
}
// call the original code.
DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};
//============================================================================
// Formatters
//============================================================================
// This formatter ensures that "~<data>" is rendered as "<data>". This is used to
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
name: "data-escape",
match: "~<\\/?data>",
handler: function(w) {
w.outputText(w.output,w.matchStart + 1,w.nextMatch);
}
} );
// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
name: "data",
match: "<data>",
handler: function(w) {
var info = DataTiddler.getDataSectionInfo(w.source);
if (info && info.prefixEnd == w.matchStart) {
w.nextMatch = info.suffixStart;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
} );
//============================================================================
// Tiddler Class Extension
//============================================================================
// "Hijack" the changed method ---------------------------------------------------
DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;
// Define accessor methods -------------------------------------------------------
// Returns the value of the given data field of the tiddler. When no such field
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
return (field)
? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
: DataTiddler.getTiddlerDataObject(this);
};
// Sets the value of the given data field of the tiddler to the value. When the
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};
//============================================================================
// showData Macro
//============================================================================
config.macros.showData = {
// Standard Properties
label: "showData",
prompt: "Display the values stored in the data section of the tiddler"
};
config.macros.showData.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the optional "JSON"
var showInJSONFormat = false;
if ((i < params.length) && params[i] == "JSON") {
i++;
showInJSONFormat = true;
}
var tiddlerName = story.findContainingTiddler(place).id.substr(7);
if (i < params.length) {
tiddlerName = params[i];
i++;
}
// --- Processing ------------------------------------------
try {
if (showInJSONFormat) {
this.renderDataInJSONFormat(place, tiddlerName);
} else {
this.renderDataAsTable(place, tiddlerName);
}
} catch (e) {
this.createErrorElement(place, e);
}
};
config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
var text = DataTiddler.getDataText(tiddlerName);
if (text) {
createTiddlyElement(place,"pre",null,null,text);
}
};
config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
var text = "|!Name|!Value|\n";
var data = DataTiddler.getDataObject(tiddlerName);
if (data) {
for (var i in data) {
var value = data[i];
text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
}
}
wikify(text, place);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.showData.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".showDataError{color: #ffffff;background-color: #880000;}",
"showData");
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... TiddlyWiki Core
/*global createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global DataTiddler */
// ... JSON
/*global JSON */
/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
throw a 'JSONError' exception if there is an error.
*/
var JSON = {
copyright: '(c)2005 JSON.org',
license: 'http://www.crockford.com/JSON/license.html',
/*
Stringify a JavaScript value, producing a JSON text.
*/
stringify: function (v) {
var a = [];
/*
Emit a string.
*/
function e(s) {
a[a.length] = s;
}
/*
Convert a value.
*/
function g(x) {
var c, i, l, v;
switch (typeof x) {
case 'object':
if (x) {
if (x instanceof Array) {
e('[');
l = a.length;
for (i = 0; i < x.length; i += 1) {
v = x[i];
if (typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(v);
}
}
e(']');
return;
} else if (typeof x.toString != 'undefined') {
e('{');
l = a.length;
for (i in x) {
v = x[i];
if (x.hasOwnProperty(i) &&
typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(i);
e(':');
g(v);
}
}
return e('}');
}
}
e('null');
return;
case 'number':
e(isFinite(x) ? +x : 'null');
return;
case 'string':
l = x.length;
e('"');
for (i = 0; i < l; i += 1) {
c = x.charAt(i);
if (c >= ' ') {
if (c == '\\' || c == '"') {
e('\\');
}
e(c);
} else {
switch (c) {
case '\b':
e('\\b');
break;
case '\f':
e('\\f');
break;
case '\n':
e('\\n');
break;
case '\r':
e('\\r');
break;
case '\t':
e('\\t');
break;
default:
c = c.charCodeAt();
e('\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16));
}
}
}
e('"');
return;
case 'boolean':
e(String(x));
return;
default:
e('null');
return;
}
}
g(v);
return a.join('');
},
/*
Parse a JSON text, producing a JavaScript value.
*/
parse: function (text) {
var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
token,
operator;
function error(m, t) {
throw {
name: 'JSONError',
message: m,
text: t || operator || token
};
}
function next(b) {
if (b && b != operator) {
error("Expected '" + b + "'");
}
if (text) {
var t = p.exec(text);
if (t) {
if (t[2]) {
token = null;
operator = t[2];
} else {
operator = null;
try {
token = eval(t[1]);
} catch (e) {
error("Bad token", t[1]);
}
}
text = text.substring(t[0].length);
} else {
error("Unrecognized token", text);
}
} else {
token = operator = undefined;
}
}
function val() {
var k, o;
switch (operator) {
case '{':
next('{');
o = {};
if (operator != '}') {
for (;;) {
if (operator || typeof token != 'string') {
error("Missing key");
}
k = token;
next();
next(':');
o[k] = val();
if (operator != ',') {
break;
}
next(',');
}
}
next('}');
return o;
case '[':
next('[');
o = [];
if (operator != ']') {
for (;;) {
o.push(val());
if (operator != ',') {
break;
}
next(',');
}
}
next(']');
return o;
default:
if (operator !== null) {
error("Missing value");
}
k = token;
next();
return k;
}
}
next();
return val();
}
};
/***
!Setup the data serialization
***/
DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;
//}}}
[[Overview Of Document Management System]]
Germ: 12
Yield: 58
Comments: Full sun.
/%
|Name|GardenView|
|Source|http://www.TiddlyTools.com/#BookmarkList|
|Version|1.0.0|
|Author|Mark S based on original by Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|Given a list of slice names, a tag, and perhaps other criteria, generates table from slices in tiddlers tagged with given tag name. |
src="file:///d:/data/tw/gardenview.js"
%/<script>
var myTag="seedaction" ;
var sliceList= "Date,Item,GermETA,YieldETA,Germ,Yield,Comments" ;
var fmt = '| %0 |%1 | %2 | %3 | %4 | %5 |%6 |%7|' ;
var out = new Array() ;
out.push("|sortable|k") ;
out.push("|! Date |! Item |! ~GermETA |! Germ |! ~YieldETA |! Yield |! Comments|!Goto|h" ) ;
fcnGetRelatedDate = function(d,offset) {
return (
new Date(
Date.convertFromYYYYMMDDHHMM( d.split("-").join("") ).getTime() +
parseInt(offset ) * 24*60*60*1000
)
).convertToYYYYMMDDHHMM().substr(4,4) ;
}
var tids=store.getTaggedTiddlers(myTag);
for (var i=0; i<tids.length; i++) {
var t=tids[i].title;
var slices = new Array() ;
var d = store.getTiddlerSlice(t,"Date" ) ;
var itm = store.getTiddlerSlice(t,"Item" ) ;
var germ = store.getTiddlerSlice(itm,"Germ") ;
var yield = store.getTiddlerSlice(itm,"Yield") ;
//wikify("Here is the germ for " + itm + ": " + germ ,place) ;
var geta = fcnGetRelatedDate(d,germ) ;
var yeta = fcnGetRelatedDate(d,yield) ;
var edit = "[[link|" + t + "]]" ;
//var geta = (
// new Date(
// Date.convertFromYYYYMMDDHHMM( d.split("-").join("") ).getTime() + germ
// )
// ).convertToYYYYMMDDHHMM().substr(4,4) ;
//geta = "9999" ;
//geta = d.split("-").join("") ;
slices.push(d) ;
slices.push(itm) ;
slices.push(geta) ;
slices.push(store.getTiddlerSlice(t,"Germ" ) ) ;
//slices.push(store.getTiddlerSlice(t,"YieldETA") ) ;
slices.push(yeta) ;
slices.push(store.getTiddlerSlice(t,"Yield" ) ) ;
slices.push(store.getTiddlerSlice(t,"Comments") ) ;
slices.push(edit) ;
var strx = fmt.format(slices) ;
out.push(strx) ;
}
return out.join("\n") ;
//wikify(out.join("\n"), place) ;
</script>
<<groceryList filterby:checked reversed tiddlerdata:GroceryListMaster xregexp:#COSTCO# scratchpad:GroceryListScratchpad xregexpnot:#TJ# sort>>
<data>{"Baking, Cake mix (spice cake is good) :GRO:":true,"Baking, Flour -- white :GRO:":true,"Beverages, Coffee FILTERS :GRO:":true,"Beverages, Cola, Decaf SUGAR FREE - 6oz if competitive, Gingerale was great :GRO:":true,"Body, Bubble Bath, Children :GRO:":true,"Dairy, Eggs :GRO:TJ:":true,"Dried, Spaghetti :GRO:TJ:":true,"Frozen, Waffles :GRO:":true,"Household, Mop with set of mopheads OUT -- maybe if we buy both at once we can prolong the life of our mops :WM:":true,"Produce, Apples :GRO:":true,"Produce, Avocados if reasonable. :GRO:":true,"Produce, Onions, purple (3x) :GRO:":true,"Produce, mushrooms :GRO:":true,"Snacks, Chips, bean - more kettle OK :GRO: ":true,"Thrift, Glass pan lids, 9in ":true}</data>
/***
|Name|GroceryListPlugin|
|Source|http://marksbasement.tiddlyspot.com/#GroceryListPlugin|
|Version|0|
|Author|MarkS|
|License|Unk|
|Type|plugin|
|Requires|DataTiddlerPlugin CheckboxPlugin |
|Description|Presents a grocery list driven by a single tiddler database. Items can be checked off or managed. |
|Status|Experimental - ALPHA|
!!!!!Usage
Install the GroceryListPlugin and the supporting plugins. Put this macro in your working grocery list tiddler:
{{{<<groceryList }}}
>{{{[filterby:<checked|all>]}}}
>{{{[reversed]}}}
>{{{[sort]}}}
>{{{[regexp:<exp>]}}}
>{{{[regexpnot:<exp>]}}}
>{{{[scratchpad:<tiddler-for-scratchpad>]}}}
{{{ >>}}}
The available parameters are as follows.
''tiddlerdata:<name of tiddler>'' allows you to specify where you want the grocery data to come from. The default is GroceryData.
''filterby ''is a parameter that indicates whether the list should show all items, or just checked items.
reversed switches the display of check boxes, so that boxes that are checked will be shown as unchecked and vice-versa. Note that it is not possible to check/uncheck items permanently in this mode -- the reversed mode is primarily intended for preparing the printed list for a shopper, who will want to check off items as they shop.
''sort ''indicates that you want the list to be sorted by item name. There's usually no reason not to use this parameter, but maybe on large lists it would save time not to sort.
''regexp:<exp>'' restricts the list to just those items that match the supplied regular <exp> expression. The intended use is that some items will be coded with particular store codes. For instance, Trader Joes is indicated by :TJ: in the item list. However, in the regular expression, you need to use the pound symbol to stand in for the colon. This kludge was necessary because the colon was already being used to pass parameters to the macro.
''regexpnot:<exp>'' eliminates from the list those items that match the supplied regular <exp> expression. This allows you to suppress items for stores where you do not intend to shop.
''scratchpad:<name-of-tiddler>'' allows you to export the current subset of the grocery list into a separate tiddler. This allows you to then go an fine tune the final grocery list. This option is a work in progress.
***/
//{{{
config.macros.groceryList = {
handler: function (place, macroName, params, wikifier, paramString, tiddler)
{ // Code here
// Parameters in param can contain:
// filterby: One of [checked|unchecked|all] -- the default without filterby is to show all
// reversed: Flips the output so that true items are displayed as empty boxes
// sort: Sorts by name of item.
// tiddlerdata: Name of tiddler to use for data. Defaults to GroceryData
// regexp: semi-regular expression filter, with the exception that '#' are turned into ':' (which can't be used in tiddler macros)
// regexpnot: inverse of regexp.
var tidName="GroceryData" ;
//if (!window.story) window.story=window;
//var title=story.findContainingTiddler(place.getAttribute("tiddler");
var strx = "" ; // I use strx since str may be used in the language
var statusChecked = true ; // Checking both gives all.
var statusUnchecked = true ;
var itemx ; // This gets used for iterating through 'hashes'
//for(itemx in params) strx = strx + " " + params[itemx] ;
// Parameter processing since TW doesn't do any for you
var myParms = {} ;
//var myKeys = new Array() ;
for(i=0;i<params.length;i++) {
// strx=strx + " -- " + params[i]; }
if (params[i].indexOf(":") >= 0 ) {
var aTemp = params[i].split(":") ;
myParms[aTemp[0]] = aTemp[1] ;
//myKeys[i] = aTemp[0] ;
} else {
//myKeys[i] = params[i] ;
myParms[params[i]]=true ;
}
}
// Filtering filterby is in checked|unchecked|all (all is default if filterby not specified)
//for(i=0;i<myKeys.length;i++) { strx= strx + myKeys[i] + "==" + myParms[myKeys[i]] + " # " ; }
for(itemx in myParms) { strx= strx + itemx + "==" + myParms[itemx] + " * " ; }
//wikify(strx+"\n",place) ;
strx = "" ;
if("filterby" in myParms ) {
//wikify(myParms["filterby"],place) ;
var keyx = "filterby" ;
if(myParms[keyx]=="checked") { statusChecked = true ; statusUnchecked = false ; }
if(myParms[keyx]=="unchecked") { statusChecked = false ; statusUnchecked = true ; }
if(myParms[keyx]=="all") { statusUnchecked = true ; statusChecked = true ; }
}
var rgxp ;
if("regexp" in myParms ) {
var regstr = myParms["regexp"] ;
regstr = regstr.replace(/#/g,":") ;
rgxp = new RegExp( regstr, "i" ) ;
}
var rgxpnot ;
if("regexpnot" in myParms ) {
var regstrnot = myParms["regexpnot"] ;
regstrnot = regstrnot.replace(/#/g,":") ;
rgxpnot = new RegExp( regstrnot, "i" ) ;
}
var rev = "" ;
if("reversed" in myParms ) {
rev = "!" ;
}
// Check for tiddler data source
if("tiddlerdata" in myParms) {
tidName = myParms["tiddlerdata"] ;
}
// Get the grocery list
//wikify("tidname=" + tidName+"\n",place) ;
var grolist = store.getTiddler(tidName).data() ;
// Get the scratchpad
var scratchpad ;
if("scratchpad" in myParms) {
tidScratch = myParms["scratchpad"] ;
scratchpad = store.getTiddler(tidScratch) ;
}
// Generate keys in case we want to sort by key:
var keys = new Array() ;
var i = 0 ;
for(itemx in grolist) {
keys[i++] = itemx ;
}
if("sort" in myParms) {
keys.sort() ;
}
// Set the filter message
var filterMessage = "" ;
var filterChoice = 0 ;
if( rgxp ) filterChoice += 1 ;
if( rgxpnot ) filterChoice += 2 ;
switch(filterChoice) {
case 3 :
filterMessage = "Filtered by :" + regstr + " and NOT " + regstrnot ;
break ;
case 2 :
filterMessage = "Filtered by: NOT " + regstrnot ;
break ;
case 1 :
filterMessage = "Filtered by: " + regstr ;
}
wikify(filterMessage + "<br>",place) ;
for(i=0;i<keys.length;i++) {
itemx = keys[i] ;
// If there is a regular expression, and it fails, then skip item
if( rgxp && ! rgxp.test(itemx) ) continue ;
// If there is an inverse regular expression, and it succeeds, skip item
if( rgxpnot && rgxpnot.test(itemx) ) continue ;
if( (!grolist[itemx] && statusUnchecked) || (grolist[itemx] && statusChecked) ) {
strx=strx+"[_{place.checked="+rev+"store.getTiddler('" + tidName + "').data()['"+itemx+"'];}" +
"{store.getTiddler('"+tidName+"').setData('"+itemx+"',place.checked) ;}]" +
" "+itemx+"\n" ;
// If a scratchpad tiddler has been designated, write the data out to it
if(scratchpad) {
scratchpad.setData(itemx,true) ;
}
}
}
wikify( strx, place ) ;
//wikify( "Item status: "+strx,place) ;
}
};
//}}}
<<groceryList filterby:checked reversed xregexp:#TJ# tiddlerdata:GroceryListScratchpad xregexpnot:#TJ# sort>>
<data>{"Baking, Cake mix (spice cake is good) :GRO:":true,"Baking, Flour -- white :GRO:":true,"Beverages, Coffee FILTERS :GRO:":true,"Beverages, Cola, Decaf SUGAR FREE - 6oz if competitive, Gingerale was great :GRO:":true,"Body, Bubble Bath, Children :GRO:":true,"Dairy, Eggs :GRO:TJ:":true,"Dried, Spaghetti :GRO:TJ:":true,"Frozen, Waffles :GRO:":true,"Household, Mop with set of mopheads OUT -- maybe if we buy both at once we can prolong the life of our mops :WM:":true,"Produce, Apples :GRO:":true,"Produce, Avocados if reasonable. :GRO:":true,"Produce, Onions, purple (3x) :GRO:":true,"Produce, mushrooms :GRO:":true,"Snacks, Chips, bean - more kettle OK :GRO: ":true,"Thrift, Glass pan lids, 9in ":true}</data>
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The ~HTMLFormatting plugin allows you to ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2009.01.05 [2.4.0] in wikifyTextNodes(), pass w.highlightRegExp and w.tiddler to wikify() so that search term highlighting and tiddler-relative macro processing will work
| see [[HTMLFormattingPluginInfo]] for additional revision details |
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormattingPlugin= {major: 2, minor: 4, revision: 0, date: new Date(2009,1,5)};
// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
if (i<config.formatters.length) config.formatters[i].handler=function(w) {
if (!this.lookaheadRegExp) // fixup for TW2.0.x
this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var html=lookaheadMatch[1];
// if <nowiki> is present, just let browser handle it!
if (html.indexOf('<nowiki>')!=-1)
createTiddlyElement(w.output,"span").innerHTML=html;
else {
// if <hide linebreaks> is present, suppress wiki-style literal handling of newlines
if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
// remove all \r's added by IE textarea and mask newlines and macro brackets
html=html.replace(/\r/g,'').replace(/\n/g,'\\n').replace(/<</g,'%%(').replace(/>>/g,')%%');
// create span, let browser parse HTML
var e=createTiddlyElement(w.output,"span"); e.innerHTML=html;
// then re-render text nodes as wiki-formatted content
wikifyTextNodes(e,w);
}
w.nextMatch = this.lookaheadRegExp.lastIndex; // continue parsing
}
}
}
// wikify #text nodes that remain after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode,w)
{
function unmask(s) { return s.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n'); }
switch (theNode.nodeName.toLowerCase()) {
case 'style': case 'option': case 'select':
theNode.innerHTML=unmask(theNode.innerHTML);
break;
case 'textarea':
theNode.value=unmask(theNode.value);
break;
case '#text':
var txt=unmask(theNode.nodeValue);
var newNode=createTiddlyElement(null,"span");
theNode.parentNode.replaceChild(newNode,theNode);
wikify(txt,newNode,highlightHack,w.tiddler);
break;
default:
for (var i=0;i<theNode.childNodes.length;i++)
wikifyTextNodes(theNode.childNodes.item(i),w); // recursion
break;
}
}
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.4|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 3, date: new Date(2008,6,11)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // load a script library
// make script tag, set src, add to body to execute, then remove for cleanup
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // there is script code
if (show) // show inline script code in tiddler output
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create a link to an 'onclick' script
// add a link, define click handler, save code in link (pass 'place'), set link attributes
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place){"+fixup+"\n};_out(this);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run inline script code
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place){"+fixup+"\n};_out(w.output);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
* Early White Vienna -- Brassica oleracea -- 2009
* Plant 1/2 in deep, 2-3 in apart,
Thin: to 4 in
Germ: 3
Germ in 3-10 days
Yield: 55
* 300 seeds
!!!Why not FET
People are drawn to the For-Each-Tiddler (FET) plugin and technology because of its easy, SQL-like language structure. AND, perhaps more importantly, it is reasonably documented, with lots and lots of examples. But there are problems. Those problems include:
!!!!Encourages data structures based on tags.
Tags are great, but they're not meant to be replacements for actual data field equivalents. They're meant to indicate the particular character of a tiddler, and not for conveying detailed information that should be inside the tiddler itself. For one thing, you can be comfortable putting long extended bits of information into real fields. Address information like "1600 Pennsylvania Avenue" would make sense in a field. But although some people would do it, it doesn't make sense in a tag field. But gee, that tag field, with its big open form field, is just so darn convenient. As we used to say, "When all you have is a hammer, everything starts to look like a nail". But have no fear, there are easy ways to create field-like objects without the tag field.
!!!!Inability to access data structures like fields, sections, slices.
One of the easiest ways to structure data in TiddlyWiki is to add it as a //slice// or //section//. More about these data structures later. You probably can use these data structures in FET, but as far as I know there are no examples in the FET site.
!!!!Frequently necessary to write javascript anyways.
As soon as you hit a certain level of complexity, you're going to have to write some supporting Javascript. And it might be a bit convoluted in order to accomodate the needs of the FET. If you're going to have to write javascript anyways, why not do it from the start?
!!!!Javascript is easy!
Relatively speaking, javascript is an easy language. As long as you don't worry your pretty (or not) little head about the DOM, inheritance, or other uppity tech matters, javascript is only slightly more complex than learning how to use the FET.
!!!The approach
My approach here is definitely cookie cutter. But there's nothing wrong with cookies. In fact, I think I'm going to have one right now. Mmmm...
!!!Setting up
To follow the examples in this tutorial, you're going to need to set up the InlineJavascriptPlugin from tiddlytools.com. Install the regular way. This plugin makes it possible to insert {{{<script>...</script>}}} tags into your tiddler, and run the code right inside your tiddler.
"But wait!," you might say. "Aren't we just substituting one Plugin for another?" No, for two reasons. For one, the script run by the InlineJavascriptPlugin doesn't need to be parsed the way the language used by the FET technology does. It just gets packed together and passed through Javascript's own parsing engine. For another, the scripting used inside of the InlineJavascriptPlugin can also be used inside of TiddlyWiki macros and tiddler transclusions.
!!!Learning to loop in Javascript
The main thing FET gives you is the ability to loop. Frequently a task you want to accomplish is to select all the items that match a particular tag. So let's start with the equivalent task using Javascript by itself.
Ok, let's get the difficult part over. In Javascript, as well as most C-like languages, you will see essentially the same construction for looping over and over. This construction is known as the "for" loop. It is very, very common and ubiquitous (look it up). Some of the variables may vary (that's what they do) but the construction itself is much the same. So why not just memorize it and have it done with:
{{{
var out = '' ;
var tiddlerArray = (array of tiddlers we want) ;
for(var i=0;i<tiddlerArray.length;i++) {
<do stuff over and over here>
}
}}}
Here we take the variable "i", initialize it to zero, compare it to "tiddlerArray.length", run the loop once, increment the i variable, and then start over. Why the {{{for(;;)}}} construction? Somebody thought it was really cook in 1970, and now its part of the landscape of a half-dozen languages. Live with it. Love it. Move on. Just like your cat.
But of course, you want to see how this plays out in real life. Let's take an example:
> //List the first 10 tiddlers that have the tag 'basic'//
!!!DIY API
If you're familiar with other programming languages, then the //for// construct was old-hat to you. Or maybe even old sombrero. That part that's not familiar is, how to do certain tasks in the context of the TiddlyWiki system. Tasks like getting all the tiddlers that match a particular tag. In other systems, there are official API's explaining how key functions work. Unfortunately, AFAIK, there is no official listing or resource. However, there is an unofficial API [[here.|http://www.tiddlytools.com/insideTW/]] This document, though good, doesn't explain how the various functions are to be used. But there are key functions that get used over and over, are fairly well understood, and are worth remembering.
!!!!API: ''getTaggedTiddlers''
Let's start with one that's very useful for collecting tiddlers by tags:
> {{{store.getTaggedTiddlers(tag) ;}}}
If you look for "store" in the above mentioned API, you probably won't find it. //store// refers to a global variable made available throughout the TiddlyWiki library, which is the instantiation of the TiddlyWiki class. Did that sound like gibberish to you? Great! Forget I mentioned it! Just know that throughout your code you will be accessing a ''store'' of Tiddlers via functions that are named with ''store'', a dot ''.'', and the function name.
When we fetch our list of tiddlers, the result will be an //array//. We will need to have some place to store that array, so we will assign it to a variable.
So, getting, back to our intended example:
> {{{List the first 10 tiddlers that have the tag 'basic'}}}
We would create our variable, using the creative variable, //tiddlerArray//, like this:
{{{
var tiddlerArray=store.getTaggedTiddlers('basic') ;
}}}
There, now we have a variable, //tiddlerArray//, filled with the names of tiddlers that are tagged as 'basic'. Arrays in Javascript have a property, called //length//, that tells you how many items have been stored in the array. We can feed this value into our //for// loop to tell the script how many times to repeat. Please note that this particular function returns tiddler objects -- //not tiddler names//. We will also want to initialize a variable to hold our results, which we will call //out//. Including our loop, what we have so far is:
{{{
var out = '' ;
var tiddlerArray = store.getTaggedTiddlers('basic') ;
for(var i=0;i<tiddlerArray.length;i++) {
<do stuff over and over here>
}
}}}
!!!!Twiddling with Conditionals
Ok, we still don't know what goes in {{{<do stuff over and over here>}}}, and there's one more problem. The original objective was to limit the results to the first 10. How are we going to make sure that we don't list more than 10 results? Let's take another look at the //for// loop:
{{{
for(var i=0;i<tiddlerArray.length;i++) {...}
}}}
The middle part of the //for// loop, the part between the two semi-colons, is the part where we can set the limits to the search. Currently we have it iterating over the entire length of the variable //tiddlerArray//, but we can add additional restraints.
In C-like languages, we can add criteria to a conditional expression by use of logical symbols ''or'' and ''and''. A logical ''or'' is expressed by ''||'' (two pipes) and a logical ''and'' is expressed by ''&&'' (two ampersands). So we can add the restraint to the //for// expression like this:
{{{
for(var i=0;i<10 || i<tiddlerArray.length ;i++) {...}
}}}
We have now asked the //for// loop to work until the counter variable //i// is less than 10, or less than the value of //tiddlerArray.length//. Now how do we list the results?
!!!!API: ''wikify''
In javascript textbooks, you may have seen output created by statements like //document.write(...)//. In the TiddlyWiki world, we can't do that. //document.write// extrudes its output wherever it happens to be when the script is invoked. Since your TiddlyWiki is a dynamic document, and redrawn on the fly, your output may not end up inside of the tiddler, or even on the page! Instead, inside of most TiddlyWiki scripts, you will want to use the //''wikify()''// function. It takes a form like:
> ''wikify("your text here",place)''
"What is //place//," you might ask? Place is a contextual variable that the //wikify// function needs in order to put the output exactly where you want it. Fortunately for you, when using //wikify// and the InlineJavascriptPlugin, you can simply use the variable 'place' as shown -- its already provided for you. Its can also be provided inside of macros and transcluded tiddlers, depending on they are set up. But it is important to remember to use the variable 'place'. Without it, you'll get a syntax error when you run your script.
Germ: 7
Yield: 46
Thin: 8 in
Comments: Germination date not stated. FamousBrand from Walmart. 46 Days. Sell by 11/09
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
config.macros.MAS_AllTagsSortedByModDate = {} ;
merge(config.macros.MAS_AllTagsSortedByModDate,{
tooltip: "Show tiddlers tagged with '%0'",
noTags: "There are no tagged tiddlers"});
config.macros.MAS_AllTagsSortedByModDate.handler = function(place,macroName,params)
{
//var tags = store.getTags(params[0]);
var order = params[1] ; // A ascend D descend
order = (order == 'A' ) ? 1 : -1 ; //
//alert(order) ;
var tags = [];
var excludeTag = params[0] ;
this.MAStag = function(tagname,count,mod) {
this.tagname = tagname;
this.count = count ;
this.mod = mod ;
}
var MAStag = this.MAStag ;
store.forEachTiddler(function (title, tiddler) {
for (var g = 0; g < tiddler.tags.length; g++) {
var tagname = tiddler.tags[g];
var tag = new MAStag(tagname,0,tiddler.modified) ;
var n = true;
for (var c = 0; c < tags.length; c++) {
if (tags[c].tagname == tagname) {
n = false;
tags[c].count++;
tags[c].mod = (tiddler.modified > tags[c].mod) ? tiddler.modified : tags[c].mod ;
}
}
if (n && excludeTag) {
var t = this.fetchTiddler(tagname);
if (t && t.isTagged(excludeTag)) {n = false;}
}
//if (n) {tags.push([tag, 1]);}
if (n) {
tags.push(new MAStag(tagname,1,tiddler.modified) );}
}
});
tags.sort(function (a, b) {return a.mod < b.mod ? -order : a.mod == b.mod ? 0 : order;});
var ul = createTiddlyElement(place,"ul");
if(tags.length == 0)
createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
for(var t=0; t<tags.length; t++) {
// var title = tags[t][0];
var title = tags[t].tagname;
var info = getTiddlyLinkInfo(title);
var li = createTiddlyElement(ul,"li");
//var btn = createTiddlyButton(li,title + " (" + tags[t][1] + ")",this.tooltip.format([title]),onClickTag,info.classes);
var btn = createTiddlyButton(li,title + " (" + tags[t].count + ")",this.tooltip.format([title]),onClickTag,info.classes);
btn.setAttribute("tag",title);
btn.setAttribute("refresh","link");
btn.setAttribute("tiddlyLink",title);
}
};
// /% <<MAS_AllTagsSortedByModDate excludeLists D>> <<allTags excludeLists>> %/
[[Compact 2009 Calendar|CompressedCalendar2009]]
----
[[SplitTextIntoTiddlers]]
----
GardenView
----
[[WiddleTest]] [[tiddleWiddlePlugin]]
----
[[webRenderTest]]
[[webRenderPlugin]]
----
[[GroceryListMaster]]
----
[[Compile Story Script|CompileStoryIntoFirstTiddler]]
<<tiddler CompileStoryIntoFirstTiddler>>
----
[[SVG Test|SVGTest]]
[[SVG Plugin|SVGMacro]]
[[WelcomeToTiddlyspot]] [[GettingStarted]]
----
[[Zoom Image Example|ZoomImageExample]]
----
[[Overview Of Document Management System]]
----
[[Life without FET|Learning to live without FET Part Uno]]
<!-- script src="temp.js" >
</script -->
Comments: from Acme (73524) , Mix of tendergreen, red giant, sawtooth, osaka purple, and green wave. Likes water
Yield: 30
Germ: 7
Thin: 6 in
Germ in 7 to 10 days. Yield in 30 to 50 days.
Likes water.
Germ: 10
Yield: 90
Thin: 12 in
Comments: Nail file to speed germination. Full sun to partial shade. Yield date is estimate, since no date on package.
|Germ: | 7|
|Yield: | 90|
|Text: | Hales best. Sunny.
This is the note that Mark wrote
Date: 2009-04-05
Item: FairyNorseOkra
Germ: 0418
Yield: ?
Comments: Transferred 4/22. Start in green house
!Overview
The plan here is to bring together several features from existing TW technologies in order to create a workable, portable, personal document management system. The idea is to make it easy to handle albums of photos, personal documents, website markers, all with one unified system. Bookmarks will be created and viewed in a manner so that they are easily recognized by their associated thumbnail images. Images and documents will not actually be stored in the physical TW -- this is infeasible with the current state of javascript technology.
!Key concepts
!!Drag and drop sourcing
Most modern applications depend on drag-and-drop for their normal operations. This process is intuitive to most individuals. Unfortunately, file drag-and-drop is currently only supported under Firefox. However, even if the data needs to be entered via a TW on FireFox, the other features of this system should still be available with other browsers.
Files or image tokens for files will be dropped onto the TW. Based on the directory pathing, tiddlers will be created for each file, with a customized "bookmark" depending on the source of the incoming file.
!!Unified file pathing
File and directory information within each bookmark will use a unified file pathing system like:
> ''URL'':"""//CDDRIVE/FH000001.jpg"""
> ''Thumb'':"""//CDS/20061204/fh000001.jpg"""
Here ''CDDRIVE'' refers to the CD drive of the local machine, which is going to vary from platform to platform and machine to machine. The ''Thumb'' notation contains a reference to a """//CDS""" directory, which in this case refers to a directory of thumbnail images, most likely on the local hard drive or possibly USB stick. The location for the directory will vary, depending on operating system and machine, so this information is tokenized as a variable that can be set in each scenario.
!!Pathing and templating
A configuration string will allow the user to define key paths and templates for whatever machine they happen to be on. A reasonable example might be:
> CDDRIVE=e:=DragDropCDTemplate;CDS=d:/data/cds=DragDropCDTemplate;
> SCREENS=d:/data/tw/screens=DragDropTemplate;
> TW=d:/data/tw=DragDropTemplate;DATA=d:/data=DragDropTemplate
Here we see that a token is assigned to each path, and each path in turn is assigned a template. As files are dropped onto the TW, this pathing information is used to determine both what token to store in the resulting bookmarks, and what template to assign for formatting the bookmark as it is created.
!!Dynamic Usage.
Bookmarks that are created will in turn be typically viewed via a form-based template, made possible by the ~TaggedTemplateTweak. This will allow individual bookmarks to be updated while still viewing the accompanying thumbnail. All the bookmarks in a set of bookmarks will share a common "parent-by-tag" tiddler. That parent tiddler can be assigned a tag that will allow it to display all the child tiddlers in a grid depending on the nature of the tiddlers. So in the case of CD bookmarks, clicking on a thumbnail image might take you to the larger image stored on CD (assuming the CD has been mounted). But in the case of Web bookmarks, clicking on the thumbnail image might take you to the source web page.
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
Date: 2009-04-10
Item: PeaNationalSeedLittleMarvel
Germ: 0423
Yield: ?
Comments: Row East in S. garden
Germ: 8
Yield: 60
Thin: 6 in apart
Germ: 10
Germ in 10 to 20 days
Yield: 70
Comments: Emerges at 75 - 80F
Date: 2009-05-01
Item: PumpkinFamousBrandEarlySweet
Germ: 0508
Yield: ?
Comments: Started in green house. Transplanted 05/13
Date: 2009-05-01
Item: PumpkinFamousBrandHercules
Germ: 0506
Yield: ?
Comments: Started in green house. Transplanted 05/13
Germ: 7
Yield: 90
Thin: 2 to 3 per hill when 1-2" high
Comment: Germ in 7 - 14 days. Fine orange flesh. 6 - 7 lbs.
Germ: 7
Yield: 110
Thin: 2 to 3 per hill when 1-2" high
Comment: Germ in 7 - 14 days.
Date: 2009-05-03
Item: PumpkinInCompost
Germ: ?
Yield: ?
Comments: Date is transplant date. Since the halloween pumpkin was doing so well in the compost bin, thought to try transplating it. Has lots of sow bugs though.
Date: 2009-05-03
Item: RadishCrimsonGiant
Germ: ?
Yield: ?
Comments: In planter box A. Was dug by fox (?) on first night.
Comments: Radish, Cherry Belle from FamousBrand/Walmart.
Yield: 22
Germ: 4
Thin: 2 in
Germ in 4 to 6 days
Comments: Radish, Crimso Giant by FamousBrand/Walmart. Germ in 4 to 6 days. 1.5" across.
Yield: 29
Thin: 2 in
Germ: 4
config.macros.SVG =
{ handler: function (place, macroName, params, wikifier, paramString,
tiddler)
{ var svg = params[0] ;
var svgObject = document.createElement('object');
svgObject.setAttribute('type', 'image/svg+xml');
svgObject.setAttribute('data', 'data:image/svg+xml,'+ '<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'+
svg +'</svg>' );
jQuery(place).append(svgObject);
}
};
<<SVG "<circle r='50' cx='50' cy='50' fill='green'/>">>
Date: 2009-mm-dd
Item: seedPacket
GermETA: mmdd
YieldETA: mmdd
Germ: ?
Yield: ?
Comments:
<<search>><<closeAll>><<permaview>><<newTiddler>><<newTiddler
label:"new seed tiddler"
text:{{store.getTiddlerText("SeedTemplate","")}}
tag:seed
>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<tiddler TspotSidebar>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
Give me a break! Its dark down here.
Text at least 30 days old
Germ: 6
Yield: 78
* Thin to 10 inches apart
* Germ 6-10 days
Comments: Vital Green, spinacia oleracea -- 2009
* plant 3/4 inch deep
* 2 to 3 in apart
Thin: to 4 in
Germ: 6
Germ in 6-14 days
Yield: 40
/%
|Name|SplitTextIntoTiddlers|
|Source|http://marksbasement.Tiddlyspot.com/#SplitTextIntoTiddlers|
|Version|0.0.3|
|Author|Mark S.|
|License|Various|
|~CoreVersion|2.5.2 or later|
|Type|html|
|Overrides||
|Description|Split long text into individual tiddlers suitable for use in TiddlyPocket book|
|Requires|StyleSheetShortcuts for appearance|
Usage:
Paste text to be split into text area box. Select how many characters you want per page. This is an upper limit, as the script will attempt to make the page break at the last word before the specified number of characters. Select how many pages you want to be created. Select the stem name that you want to use for the resulting tiddlers. If you are going generate more than 10 tiddlers, you might also want to specify the padding for the output so that the resulting tiddlers can be split correctly.
Then press the submit button to run. After a few seconds, the tiddlers that are generated should appear in your timeline. The script will not open them in the display area, in case you are creating a lot.
If the stem name you select represents an actual tiddler, then that tiddler will be used as a template for tags, fields, user name, and date.
Any text that could not be cut into the specified number of tiddlers remains in the text box, so that you can then specify a second stem name and run the process again if so desired.
%/
{{smallform{
<html><hide linebreaks><nowiki><!-- see HTMLFormattingPlugin --><form action="javascript:;"
onsubmit='
var tiddlerStem = this.stem.value ; // Tiddlers to be created will each start with this name
var splitAfter = parseInt(this.unitCount.value) ; // Split data every x characters or every x lines
var spin = 1 ; // Keeps track of tiddler extension number
var data = this.txtData.value ;
var maxPage = parseInt(this.maxPage.value) ;
var numPad = parseInt(this.numPad.value ) ;
var prepend = this.prepend.value?this.prepend.value:"" ;
var postpend = this.postpend.value?this.postpend.value:"" ;
var splitType = "noneoftheabove" ;
for(var i=0;i<2;i++) { // YOU WILL NEED TO CHANGE THIS IF YOU ADD RADIO BUTTONS
if(this.splitType[i].checked) {splitType = this.splitType[i].value; break;}
}
var tid=store.getTiddler(tiddlerStem);
var who=tid?tid.modifier:config.options.txtUserName;
var when=tid?tid.modified:new Date();
var tags=tid?tid.tags:(this.tags.value?this.tags.value:[]);
var fields=tid?tid.fields:{};
//alert("x"+splitType+"x") ;
if(splitType=="char") {
while(data.length && spin <= maxPage ) {
var newTitle = tiddlerStem + String.zeroPad(spin,numPad) ;
var chunk = data.slice(0,Math.min(splitAfter,data.length)) ;
var lastWord = chunk.search(/\w\S*$/) ;
if (chunk.length == data.length || lastWord == -1 ) {
lastWord = chunk.length ;
}
chunk = chunk.slice(0,lastWord) ;
store.saveTiddler(newTitle, newTitle, prepend+chunk+postpend, who, when, tags, fields); ;
data = data.slice(lastWord,data.length) ;
spin++ ;
}
this.txtData.value = data ;
} // SPLIT BY CHAR ROUTINE
if(splitType=="line") {
var lines = data.split(/\n/g) ;
var startPt = 0 ;
var endPt = Math.min(lines.length,splitAfter) ;
for(var pageNum=0;pageNum<maxPage;pageNum++) {
//alert("start %0 end %1".format([startPt,endPt])) ;
if ( ! lines.length || startPt > lines.length || startPt==endPt) break ;
var pageText = lines.slice(startPt,endPt).join("\n") ;
var newTitle = tiddlerStem + String.zeroPad(pageNum+1,numPad) ;
store.saveTiddler(newTitle, newTitle, prepend+pageText+postpend, who, when, tags, fields); ;
startPt += splitAfter ;
endPt = Math.min(lines.length,endPt+splitAfter) ;
}
if(startPt <= endPt) { this.txtData.value = lines.slice(startPt,endPt).join("\n") } else
this.txtData.value = "" ;
} // SPLIT BY LINE ROUTINE
//wikify(data,place) ;
return false ;
'>
<table class="borderless" width="80%">
<tr><td colspan="2"><b>Text to be split</b><br>
<textarea name="txtData" cols="80%" rows="10" ></textarea></td></tr>
<tr><td width="100" ><b>Tiddler Stem name: </b></td> <td><input name="stem" type="text" size="30" value="TiddlerToBe"
onchange="this.form.tags.value=this.value;"></td></tr>
<tr><td width="100" ><b>Tags: </b></td> <td><input name="tags" type="text" size="50" value="TiddlerToBe"></td></tr>
<tr><td width="100" ><b>Divide by: </b></td><td>
<input name="splitType" type="radio" checked value="char"
onchange="jQuery('#lblCount').text('Char.s per page:');this.form.unitCount.value='400';"
>Char. Count
<input name="splitType" type="radio" value="line" onchange="jQuery('#lblCount').text('Lines per page:');this.form.unitCount.value='20'">Line Count
</td></tr>
<tr><td width="100" colspan="2"><b><span id="lblCount">Char.s per page:</span> </b> <input name="unitCount" type="text" size="5" value="400">
<b>Max. # of pages: </b><input name="maxPage" type="text" size="5" value="8">
<b> Pad # of digits: </b><input name="numPad" type="text" size="5" value="1"></td></tr>
<tr><td width="100" ><b>Prepend: </b></td> <td><input name="prepend" type="text" size="30" value="@@font-size:x-small;"></td></tr>
<tr><td width="100" ><b>Postpend: </b></td> <td><input name="postpend" type="text" size="30" value="@@"></td></tr>
</table>
<input type="submit" value="Split Text">
</form></html>
Germ: 6
Germ 6 to 10 days
Yield: 90
Thin: 2 plants per hill
Comments: 14982. Plant 1 inc deep, 4 to 5 per hill, 6 feet apart. Prefers light, well fertilized soil.
Yield: 140
Germ: 6
Thin: 2 plants per hill
Comments: Squash, Winter, Hybrid. Packet 66325. Germ 6-10 days. 140 days.
Should produce 15-27 inch fruits weighing over 30 pounds.
.viewer div.centeredTable {
text-align: center;
}
.viewer div.centeredTable table {
margin: 0 auto;
text-align: left;
}
[[StyleSheetShortcuts]]
/***
|Name|StyleSheetShortcuts|
|Source|http://www.TiddlyTools.com/#StyleSheetShortcuts|
|Version||
|Author|Eric Shulman|
|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|CSS|
|Requires||
|Overrides||
|Description|'convenience' classes for common formatting, alignment, boxes, tables, etc.|
These 'style tweaks' can be easily included in other stylesheet tiddler so they can share a baseline look-and-feel that can then be customized to create a wide variety of 'flavors'.
***/
/*{{{*/
/* text alignments */
.left
{ display:block;text-align:left; }
.center
{ display:block;text-align:center; }
.center table
{ margin:auto !important; }
.right
{ display:block;text-align:right; }
.justify
{ display:block;text-align:justify; }
.indent
{ display:block;margin:0;padding:0;border:0;margin-left:2em; }
.floatleft
{ float:left; }
.floatright
{ float:right; }
.valignTop, .valignTop table, .valignTop tbody, .valignTop th, .valignTop tr, .valignTop td
{ vertical-align:top; }
.valignBottom, .valignBottom table, .valignBottom tbody, .valignBottom th, .valignBottom tr, .valignBottom td
{ vertical-align:bottom; }
.clear
{ clear:both; }
.wrap
{ white-space:normal; }
.nowrap
{ white-space:nowrap; }
.hidden
{ display:none; }
.show
{ display:inline !important; }
.span
{ display:span; }
.block
{ display:block; }
.relative
{ position:relative; }
.absolute
{ position:absolute; }
/* font sizes */
.big
{ font-size:14pt;line-height:120% }
.medium
{ font-size:12pt;line-height:120% }
.normal
{ font-size:9pt;line-height:120% }
.small
{ font-size:8pt;line-height:120% }
.fine
{ font-size:7pt;line-height:120% }
.tiny
{ font-size:6pt;line-height:120% }
.larger
{ font-size:120%; }
.smaller
{ font-size:80%; }
/* font styles */
.bold
{ font-weight:bold; }
.italic
{ font-style:italic; }
.underline
{ text-decoration:underline; }
/* plain list items (no bullets or indent) */
.nobullets li { list-style-type: none; margin-left:-2em; }
/* multi-column tiddler content (not supported in Internet Explorer) */
.twocolumns { display:block;
-moz-column-count:2; -moz-column-gap:1em; -moz-column-width:50%; /* FireFox */
-webkit-column-count:2; -webkit-column-gap:1em; -webkit-column-width:50%; /* Safari */
column-count:2; column-gap:1em; column-width:50%; /* Opera */
}
.threecolumns { display:block;
-moz-column-count:3; -moz-column-gap:1em; -moz-column-width:33%; /* FireFox */
-webkit-column-count:3; -webkit-column-gap:1em; -webkit-column-width:33%; /* Safari */
column-count:3; column-gap:1em; column-width:33%; /* Opera */
}
.fourcolumns { display:block;
-moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%; /* FireFox */
-webkit-column-count:4; -webkit-column-gap:1em; -webkit-column-width:25%; /* Safari */
column-count:4; column-gap:1em; column-width:25%; /* Opera */
}
/* show/hide browser-specific content for InternetExplorer vs. non-IE ("moz") browsers */
*[class="ieOnly"]
{ display:none; } /* hide in moz (uses CSS selector) */
* html .mozOnly, *:first-child+html .mozOnly
{ display: none; } /* hide in IE (uses IE6/IE7 CSS hacks) */
/* borderless tables */
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody
{ border:0 !important; margin:0 !important; padding:0 !important; }
.widetable, .widetable table
{ width:100%; }
/* thumbnail images (fixed-sized scaled images) */
.thumbnail img { height:5em !important; }
/* stretchable images (auto-size to fit tiddler) */
.stretch img { width:95%; }
/* grouped content */
.outline
{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; }
.menubox
{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#fff; color:#000; }
.menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting
{ color:#009 !important; }
.groupbox
{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#ffe; color:#000; }
.groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting
{ color:#009 !important; }
.groupbox code
{ color:#333 !important; }
.borderleft
{ margin:0;padding:0;border:0;margin-left:1em; border-left:1px dotted; padding-left:.5em; }
.borderright
{ margin:0;padding:0;border:0;margin-right:1em; border-right:1px dotted; padding-right:.5em; }
.borderbottom
{ margin:0;padding:1px 0;border:0;border-bottom:1px dotted; margin-bottom:1px; padding-bottom:1px; }
.bordertop
{ margin:0;padding:0;border:0;border-top:1px dotted; margin-top:1px; padding-top:1px; }
/* scrolled content */
.scrollbars { overflow:auto; }
.height10em { height:10em; }
.height15em { height:15em; }
.height20em { height:20em; }
.height25em { height:25em; }
.height30em { height:30em; }
.height35em { height:35em; }
.height40em { height:40em; }
/* compact form */
.smallform
{ white-space:nowrap; }
.smallform input, .smallform textarea, .smallform button, .smallform checkbox, .smallform radio, .smallform select
{ font-size:8pt; }
/* stretchable edit fields and textareas (auto-size to fit tiddler) */
.stretch input { width:99%; }
.stretch textarea { width:99%; }
/* compact input fields (limited to a few characters for entering percentages and other small values) */
.onechar input { width:1em; }
.twochar input { width:2em; }
.threechar input { width:3em; }
.fourchar input { width:4em; }
.fivechar input { width:5em; }
/* text colors */
.white { color:#fff !important }
.gray { color:#999 !important }
.black { color:#000 !important }
.red { color:#f66 !important }
.green { color:#0c0 !important }
.blue { color:#99f !important }
/* rollover highlighting */
.mouseover
{color:[[ColorPalette::TertiaryLight]] !important;}
.mouseover a
{color:[[ColorPalette::TertiaryLight]] !important;}
.selected .mouseover
{color:[[ColorPalette::Foreground]] !important;}
.selected .mouseover .button, .selected .mouseover a
{color:[[ColorPalette::PrimaryDark]] !important;}
/* rollover zoom text */
.zoomover
{ font-size:80% !important; }
.selected .zoomover
{ font-size:100% !important; }
/* [[ColorPalette]] text colors */
.Background { color:[[ColorPalette::Background]]; }
.Foreground { color:[[ColorPalette::Foreground]]; }
.PrimaryPale { color:[[ColorPalette::PrimaryPale]]; }
.PrimaryLight { color:[[ColorPalette::PrimaryLight]]; }
.PrimaryMid { color:[[ColorPalette::PrimaryMid]]; }
.PrimaryDark { color:[[ColorPalette::PrimaryDark]]; }
.SecondaryPale { color:[[ColorPalette::SecondaryPale]]; }
.SecondaryLight { color:[[ColorPalette::SecondaryLight]];}
.SecondaryMid { color:[[ColorPalette::SecondaryMid]]; }
.SecondaryDark { color:[[ColorPalette::SecondaryDark]]; }
.TertiaryPale { color:[[ColorPalette::TertiaryPale]]; }
.TertiaryLight { color:[[ColorPalette::TertiaryLight]]; }
.TertiaryMid { color:[[ColorPalette::TertiaryMid]]; }
.TertiaryDark { color:[[ColorPalette::TertiaryDark]]; }
.Error { color:[[ColorPalette::Error]]; }
/* [[ColorPalette]] background colors */
.BGBackground { background-color:[[ColorPalette::Background]]; }
.BGForeground { background-color:[[ColorPalette::Foreground]]; }
.BGPrimaryPale { background-color:[[ColorPalette::PrimaryPale]]; }
.BGPrimaryLight { background-color:[[ColorPalette::PrimaryLight]]; }
.BGPrimaryMid { background-color:[[ColorPalette::PrimaryMid]]; }
.BGPrimaryDark { background-color:[[ColorPalette::PrimaryDark]]; }
.BGSecondaryPale { background-color:[[ColorPalette::SecondaryPale]]; }
.BGSecondaryLight { background-color:[[ColorPalette::SecondaryLight]]; }
.BGSecondaryMid { background-color:[[ColorPalette::SecondaryMid]]; }
.BGSecondaryDark { background-color:[[ColorPalette::SecondaryDark]]; }
.BGTertiaryPale { background-color:[[ColorPalette::TertiaryPale]]; }
.BGTertiaryLight { background-color:[[ColorPalette::TertiaryLight]]; }
.BGTertiaryMid { background-color:[[ColorPalette::TertiaryMid]]; }
.BGTertiaryDark { background-color:[[ColorPalette::TertiaryDark]]; }
.BGError { background-color:[[ColorPalette::Error]]; }
/*}}}*/
/***
|''Name:''|TableSortingPlugin|
|''Description:''|Dynamically sort tables by clicking on column headers|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TableSortingPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.02|
|''Date:''|25-01-2008|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Usage:
* Make sure your table has a header row
** {{{|Name|Phone Number|Address|h}}}<br> Note the /h/ that denote a header row
* Give the table a class of 'sortable'
** {{{
|sortable|k
|Name|Phone Number|Address|h
}}}<br>Note the /k/ that denotes a class name being assigned to the table.
* To disallow sorting by a column, place {{{<<nosort>>}}} in it's header
* To automatically sort a table by a column, place {{{<<autosort>>}}} in the header for that column
** Or to sort automatically but in reverse order, use {{{<<autosort reverse>>}}}
!!Example:
|sortable|k
|Name |Salary |Extension |Performance |File Size |Start date |h
|ZBloggs, Fred |$12000.00 |1353 |+1.2 |74.2Kb |Aug 19, 2003 21:34:00 |
|ABloggs, Fred |$12000.00 |1353 |1.2 |3350b |09/18/2003 |
|CBloggs, Fred |$12000 |1353 |1.200 |55.2Kb |August 18, 2003 |
|DBloggs, Fred |$12000.00 |1353 |1.2 |2100b |07/18/2003 |
|Bloggs, Fred |$12000.00 |1353 |01.20 |6.156Mb |08/17/2003 05:43 |
|Turvey, Kevin |$191200.00 |2342 |-33 |1b |02/05/1979 |
|Mbogo, Arnold |$32010.12 |2755 |-21.673 |1.2Gb |09/08/1998 |
|Shakespeare, Bill |£122000.00|3211 |6 |33.22Gb |12/11/1961 |
|Shakespeare, Hamlet |£9000 |9005 |-8 |3Gb |01/01/2002 |
|Fitz, Marvin |€3300.30 |5554 |+5 |4Kb |05/22/1995 |
***/
// /%
//!BEGIN-PLUGIN-CODE
config.tableSorting = {
darrow: "\u2193",
uarrow: "\u2191",
getText : function (o) {
var p = o.cells[SORT_INDEX];
return p.innerText || p.textContent || '';
},
sortTable : function (o,rev) {
SORT_INDEX = o.getAttribute("index");
var c = config.tableSorting;
var T = findRelated(o.parentNode,"TABLE");
if(T.tBodies[0].rows.length<=1)
return;
var itm = "";
var i = 0;
while (itm == "" && i < T.tBodies[0].rows.length) {
itm = c.getText(T.tBodies[0].rows[i]).trim();
i++;
}
if (itm == "")
return;
var r = [];
var S = o.getElementsByTagName("span")[0];
c.fn = c.sortAlpha;
if(!isNaN(Date.parse(itm)))
c.fn = c.sortDate;
else if(itm.match(/^[$|£|€|\+|\-]{0,1}\d*\.{0,1}\d+$/))
c.fn = c.sortNumber;
else if(itm.match(/^\d*\.{0,1}\d+[K|M|G]{0,1}b$/))
c.fn = c.sortFile;
for(i=0; i<T.tBodies[0].rows.length; i++) {
r[i]=T.tBodies[0].rows[i];
}
r.sort(c.reSort);
if(S.firstChild.nodeValue==c.darrow || rev) {
r.reverse();
S.firstChild.nodeValue=c.uarrow;
}
else
S.firstChild.nodeValue=c.darrow;
var thead = T.getElementsByTagName('thead')[0];
var headers = thead.rows[thead.rows.length-1].cells;
for(var k=0; k<headers.length; k++) {
if(!hasClass(headers[k],"nosort"))
addClass(headers[k].getElementsByTagName("span")[0],"hidden");
}
removeClass(S,"hidden");
for(i=0; i<r.length; i++) {
T.tBodies[0].appendChild(r[i]);
c.stripe(r[i],i);
for(var j=0; j<r[i].cells.length;j++){
removeClass(r[i].cells[j],"sortedCol");
}
addClass(r[i].cells[SORT_INDEX],"sortedCol");
}
},
stripe : function (e,i){
var cl = ["oddRow","evenRow"];
i&1? cl.reverse() : cl;
removeClass(e,cl[1]);
addClass(e,cl[0]);
},
sortNumber : function(v) {
var x = parseFloat(this.getText(v).replace(/[^0-9.-]/g,''));
return isNaN(x)? 0: x;
},
sortDate : function(v) {
return Date.parse(this.getText(v));
},
sortAlpha : function(v) {
return this.getText(v).toLowerCase();
},
sortFile : function(v) {
var j, q = config.messages.sizeTemplates, s = this.getText(v);
for (var i=0; i<q.length; i++) {
if ((j = s.toLowerCase().indexOf(q[i].template.replace("%0\u00a0","").toLowerCase())) != -1)
return q[i].unit * s.substr(0,j);
}
return parseFloat(s);
},
reSort : function(a,b){
var c = config.tableSorting;
var aa = c.fn(a);
var bb = c.fn(b);
return ((aa==bb)? 0 : ((aa<bb)? -1:1));
}
};
Story.prototype.tSort_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force,customFields,defaultText){
var elem = this.tSort_refreshTiddler.apply(this,arguments);
if(elem){
var tables = elem.getElementsByTagName("TABLE");
var c = config.tableSorting;
for(var i=0; i<tables.length; i++){
if(hasClass(tables[i],"sortable")){
var x = null, rev, table = tables[i], thead = table.getElementsByTagName('thead')[0], headers = thead.rows[thead.rows.length-1].cells;
for (var j=0; j<headers.length; j++){
var h = headers[j];
if (hasClass(h,"nosort"))
continue;
h.setAttribute("index",j);
h.onclick = function(){c.sortTable(this); return false;};
h.ondblclick = stopEvent;
if(h.getElementsByTagName("span").length == 0)
createTiddlyElement(h,"span",null,"hidden",c.uarrow);
if(!x && hasClass(h,"autosort")) {
x = j;
rev = hasClass(h,"reverse");
}
}
if(x)
c.sortTable(headers[x],rev);
}
}
}
return elem;
};
setStylesheet("table.sortable span.hidden {visibility:hidden;}\n"+
"table.sortable thead {cursor:pointer;}\n"+
"table.sortable .nosort {cursor:default;}\n"+
"table.sortable td.sortedCol {background:#ffc;}","TableSortingPluginStyles");
function stopEvent(e){
var ev = e? e : window.event;
ev.cancelBubble = true;
if (ev.stopPropagation) ev.stopPropagation();
return false;
}
config.macros.nosort={
handler : function(place){
addClass(place,"nosort");
}
};
config.macros.autosort={
handler : function(place,m,p,w,pS){
addClass(place,"autosort"+" "+pS);
}
};
//!END-PLUGIN-CODE
// %/
[[TestThis|About]]<<tiddler {{place.lastChild.title='it works';''}}>>
//{{{
config.macros.tiddlerstiddled = {
handler: function (place, macroName, params, wikifier, paramString, tiddler)
{
var here=story.findContainingTiddler(place); if (!here) return;
//var tid=store.getTiddler(
curTitle = here.getAttribute('tiddler') ;
//for (var x in myTitle) {
//wikify(x + "\n",place) ;
//}
//wikify("Title: " + curTitle +"\n",place) ;
var patternText = '<<tiddler\\s+(\\[\\[){0,1}' +curTitle+'(\\]\\]){0,1}\\b' ;
//wikify("Making pattern with: " + patternText + "\n", place) ;
var pattern = new RegExp(patternText) ;
var res = store.search( pattern , "title",null) ;
for (var i=0; i<res.length; i++) {
wikify(res[i].title + "\n", place) ;
}
}
};
//}}}
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'marksbasement';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 28/02/2010 13:03:55 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . | ok |
| 28/02/2010 13:19:28 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . | ok |
| 28/02/2010 15:26:58 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . | ok |
| 28/02/2010 18:11:23 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . |
| 28/02/2010 22:00:05 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . | ok |
| 01/03/2010 06:11:45 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . | ok |
| 01/03/2010 06:34:09 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . |
| 01/03/2010 21:28:15 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . |
| 02/03/2010 10:20:13 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . |
| 04/03/2010 09:22:47 | YourName | [[index.html|http://marksbasement.tiddlyspot.com/index.html]] | [[store.cgi|http://marksbasement.tiddlyspot.com/store.cgi]] | . | [[index.html | http://marksbasement.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 3,
date: new Date("Feb 24, 2008"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
In the following macro (visible when editing), the number is the number of days to begin looking for untouched or unmodified tiddlers.
<<tiddleWiddle daysback:5 xnosys includeTags:"junk stuff morestuff" >>
<script>
var nW,nH,oH,oW;
window.zoomToggle = function(iWideSmall,iHighSmall,iWideLarge,iHighLarge,whichImage) {
oW=whichImage.style.width;oH=whichImage.style.height;
if((oW==iWideLarge)||(oH==iHighLarge))
{ nW=iWideSmall;nH=iHighSmall;}
else { nW=iWideLarge;nH=iHighLarge;} ;
whichImage.style.width=nW;whichImage.style.height=nH;}
</script>
<html>
<img border="0" src="http://www.codelifter.com/main/javascript/zoomAimage.gif" width="100" height="100"
onclick="zoomToggle('100px','100px','200px','200px',this);" >
<br>
<img border="0" src="http://www.codelifter.com/main/javascript/zoomBimage.gif" width="100" height="100"
onclick="zoomToggle('75px','75px','200px','200px',this);" >
</html>
Date: 2009-04-16
Item: ZucchiniFamousBrand
Germ: 0421
Yield: ?
Comments: Transferred 4/23. Start In green house
Germ: 10
* Germ 10 to 14 days
Yield: 48
Thin: 1 to 2 plants separated by 36"
/***
|Name|allTagsConsidered|
|Source|http://marksbasement.tiddlyspot.com/#allTagsConsidered|
|Version|0.1|
|Author|MarkS|
|License|Unk|
|Type|plugin|
|Requires||
|Description|Macro that extracts all tags in sorted order, minus tags that are not wanted, formatted per instruction|
|Status|Experimental - ALPHA|
!!!!!Usage
Don't use. Visit http://www.TiddlyTools.com/#MatchTagsPlugin for a better solution.
But, here's the rest of the documentation if you decide to use.
{{{<<allTagsConsidered FormatString Linefeed? ExcludeMe1 ExcludeMe2 ... >>}}}
Where formatString is the mandatory format string, in which %0 is a place marker for the title of the tag. Linefeed is 0 or 1, depending on whether you want a linefeed between eachi item, and the following ExcludeMe items are the tags that you don't want to appear in the list.
***/
//{{{
config.macros.allTagsConsidered = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var fmt = params[0] ;
var sep = params[1] ;
fmt = fmt.replace(/\\n/g,"<br>") ;
//wikify(fmt, place) ;
var excTags = new Array ;
for(var i = 2 ; i < params.length ; i++ ) {
excTags.push(params[i] ) ;
}
var tags = store.getTags();
for(var i = 0 ; i < excTags.length ; i++) {
var t = 0 ;
while( t < tags.length ) {
if( tags[t][0] == excTags[i] ) {
tags.splice(t,1) ;
break ;
}
t++ ;
}
}
var ul = createTiddlyElement(place, "ul");
var res = new Array ;
for (var t = 0; t < tags.length; t++) {
var title = tags[t][0];
res.push(fmt.format([title]).trim()) ;
}
if(sep) {
wikify(res.join("\n"),place) ;
} else {
wikify(res.join(""),place) ;
}
}}
//}}}
<<allTagsConsidered "|[[%0]]|" 1 "systemConfig" >>
/***
|Name|tiddleWiddlePlugin|
|Source|http://marksbasement.tiddlyspot.com/#ItiddleWiddlePlugin|
|Version|0.1|
|Author|MarkS|
|License|Unk|
|Type|plugin|
|Requires|Nothing but luck, so far|
|Description|Create a list of tiddlers that are older than a specified number of days. Provide an option to delete or restamp them with today's date.|
|Status|Experimental - ALPHA|
!!!!!Usage
The usage may evolve with subsequent editions. So please check this documentation when upgrading. current simply use
{{{<<tiddleWiddle [daysback:x] [nosys] [includeTags:"tag1 tag2"] >>}}}
inside a tiddler, where the ''x'' following the parameter ''daysback'' is the number of days at which you wish to begin looking (default 30). The flag ''nosys'' indicates that Plugins will be excluded (defaults to false). And the ''includeTags'' option allows you to specify a quoted list, separated by spaces, of tags that you wish to search for. If you use this option, then automatically any tiddler that does not contain one of the options will be excluded from the final list. This will create a list, showing something that will look like:
{{centeredTable{
|TiddlerName|200903120820|<html><a href="x">delete</a></html>|<html><a href="x">stamp</a></html>|
}}}
Clicking on __delete__ //should// delete the specified tiddler. Clicking on __stamp__ //should// update the modified stamp of the tiddler to today's date, making the item drop out of the current list. Neither of these changes should be permanent until you save the TW file.
!!!!!Future
More parameters, probably named, to allow specifying cut-off date, stamp-with date. Other features as suggested.
!!!!!Code
***/
//{{{
// Treat as BETA. Have backups before trying.
config.macros.tiddleWiddle= {
handler: function (place, macroName, params, wikifier, paramString, tiddler) {
//var compareDate = "20090310" ;
//wikify("comparing using " + compareDate,place) ; // debug
var res = [] ;
var tids = store.getTiddlers() ;
var today = (new Date).convertToYYYYMMDDHHMM() ;
var thisTidTitle = tiddler.title ;
var prms = paramString.parseParams(null, null, true);
var nosys = params.contains("nosys");
var includeTags = getParam(prms, "includeTags");
includeTags = includeTags ? includeTags.split(" ") : new Array ;
//var offset = params[0] ? params[0] : 30 ;
var daysback = getParam(prms, "daysback") ;
daysback = daysback ? daysback : 30 ;
var compareDate = (new Date( (new Date).getTime() -
daysback*24*60*60*1000)).convertToYYYYMMDDHHMM() ;
// if(nosys) {
// wikify("no system: " + nosys + "<br>",place) ;
// }
// wikify("params: " + prms + "<br>", place) ;
// wikify("includeTags: " + includeTags + "<br>", place) ;
// wikify("daysback: " + daysback + "<br>", place) ;
tiddleWiddleLoop:
for (var i=0; i<tids.length; i++) {
var t=tids[i] ;
var hallPass = true ;
if( nosys && t.tags.contains("systemConfig") ) continue ;
if (t.tags.length && includeTags.length ) {
hallPass = false ;
hallPass = t.tags.containsAny(includeTags) ;
//wikify("I see tag status " + hallPass + " in " + t.title + " -- " + includeTags + " tag size " + t.tags.length + "<br>",place) ;
}
if(! t.tags.length && includeTags.length ) {
//wikify("Disqualifying " + t.title + "<br>",place) ;
hallPass = false ;
}
if( ! hallPass ) continue ;
var mod = t.modified ? t.modified.convertToYYYYMMDDHHMM() : t.created.convertToYYYYMMDDHHMM() ;
if( mod < compareDate) {
var formattedTitle = "|[[" + t.title + "]] |" + mod + " | " +
"<html><a href=\"javascript: config.commands.deleteTiddler.handler(null,null," +
"\'" + t.title + "\'" +
"); story.refreshAllTiddlers() ; void 0; \">delete</a></html> | " +
"<html><a href=\"javascript: store.getTiddler(\'" + t.title +
"\').modified = new Date() ; story.refreshAllTiddlers() ;void 0; \">stamp</a></html> |" ;
res.push(formattedTitle) ;
}
}
wikify( res.join("\n") , place) ;
}
} ;
//}}}
/***
|Name|webRenderPlugin|
|Source|http://marksbasement.tiddlyspot.com/#webRenderPlugin|
|Version|0|
|Author|MarkS|
|License|Unk|
|Type|plugin|
|Core|2.5.0|
|Requires|2.5.0 or jQuery|
|Description|Allows quick and dirty insertion of XML feeds, including possibly RSS feeds|
|Status|Experimental - ALPHA|
!!!!!Usage
Install the webRenderPlugin and any supporting plugins. Put this macro in your working grocery list tiddler:
{{{<<webRender}}}
>{{{[url:<url string>]}}}
>{{{[fields:<field list>]}}}
>{{{[format:<format string>]}}}
{{{>>}}}
Where url is a typical url string.
The field list is a list of fields that you wish to extract, with a couple of oddities. If the XML entry you are extracting has only one element (e.g., Quote of the Day) then the first field should be an asterisk (*). Otherwise, the first field should be the "container" field for the remaining fields (e.g., the "item" field if extracting all the items in an RSS feed). There is rudimentary support for extracting attributes. Using field[attribute] will get you the value of the "attribute" of the field.
And yes, I know I should have called them elements.
The format string substitutes the first field (after the container field) for %0, the next field for %1, and so forth.
***/
//{{{
config.macros.webRender= {
handler: function (place, macroName, params, wikifier, paramString, tiddler) {
var prms = paramString.parseParams(null, null, true);
//var nosys = params.contains("nosys");
//var includeTags = getParam(prms,"includeTags");
var renderUrl = getParam(prms,"url");
var fieldList = getParam(prms,"fields").split(" ") ;
var formatString = getParam(prms,"format") ;
// item title-0 link-1 desc-2 enclosure
//formatString = "<html><a href='%1' alt='%2'>%0</a></html>" ;
//formatString = "[[%0|%1]] - [[download|%3]]<br>" ;
var keyField = fieldList[0] ; // first 'field' is container block
// 'http://www.swanandmokashi.com/HomePage/WebServices/QuoteOfTheDay.asmx/GetQuote',
//Code that allows jQuery/Ajax routines to read from other domains
if(window.Components && window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
jQuery.get(
//loadRemoteFile(
renderUrl,
null, // for jQuery
function(xml,status){ // jQuery
//function(status,place,xml,renderUrl,x){ // for loadRemoteFile
var testField = keyField ;
var attrRegExp = new RegExp(/\[|\]/g) ;
if(keyField == "*") {
var fieldVals = new Array ;
for(var i=1 ; i <= fieldList.length ; i++) {
fieldVals.push(jQuery(xml).find(fieldList[i]).text() ) ;
}
wikify(formatString.format(fieldVals),place);
} else {
//wikify("here's the raw text:<br>" + xml + "<br>" , place) ;
jQuery(xml).find(keyField).each(
function() {
var fieldVals = new Array ;
//wikify(jQuery(this).val(), place ) ;
//for ( var ky in jQuery(this) ) { wikify(ky + "<br>",place) ; }
for(var i=1 ; i < fieldList.length ; i++) {
var pushMe = "" ;
var fieldKey = fieldList[i] ;
var fieldAttr = "" ;
if(fieldKey.indexOf('[') > -1) {
fieldAttr = fieldKey.split(attrRegExp) ;
var temp = "" ;
//for(var j=0 ; j < fieldAttr.length ; j++)
// temp = temp + fieldAttr[j] + " ! " ;
//wikify("sample split for " + fieldKey + ": " + temp , place) ;
fieldAttr = fieldKey.split(attrRegExp)[1] ;
//fieldKey = fieldKey.split('.')[0] ;
pushMe = jQuery(this).find(fieldKey).attr(fieldAttr) ;
} else {
pushMe = jQuery(this).find(fieldList[i]).text() ;
}
fieldVals.push(pushMe) ;
}
wikify(formatString.format(fieldVals),place);
}
) ;
} // if()
} // loadRemoteFile.function or jQuery post/get
,
//place // for loadRemoteFile
"xml" // for jQuery-post
);
}
} ;
//}}}
This TW has to be downloaded to your computer in order for the webRender macro to render the specified site. This is part of the built-in security mechanism in javascript, so live with it, ok?
<<webRender
url:'http://www.npr.org/rss/podcast.php?id=510221'
fields:'item title link description enclosure[url]'
xformat:"''%0''<br>%1<br><br>"
format:"[[%0|%1]] - [[download|%3]]<br>"
>>
<<webRender url:'http://www.npr.org/rss/podcast.php?id=510221' xurl:'http://www.swanandmokashi.com/HomePage/WebServices/QuoteOfTheDay.asmx/GetQuote' xurl:"quotes.xml" fields:'item title link description enclosure' xfields:'Quote QuoteOfTheDay Author' format:"''%0''<br>%1<br><br>" >>