Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
|Name|CheckboxPluginInfo|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|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
<<<
/***
|''Name:''|DiffFormatterPlugin|
|''Description:''|Extension of TiddlyWiki syntax to support Diff text formatting|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Source:''|http://www.martinswiki.com/#DiffFormatterPlugin |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/DiffFormatterPlugin.js |
|''Version:''|0.0.3|
|''Date:''|Sep 11, 2009|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]] |
|''~CoreVersion:''|2.1.0|
This is an early release of the DiffFormatterPlugin, which extends the TiddlyWiki syntax to support Diff
text formatting.
The Diff formatter is different from the other formatters in that Tiddlers are not required to be
tagged: instead the Diff format adds formatting that augments TiddlyWiki's format.
The Diff formatter adds the following:
# ^+ for added
# ^- for removed
# ^"""@@ """, """--- """ and """+++ """ for special markers
Please report any defects you find at http://groups.google.co.uk/group/TiddlyWikiDev
!StyleSheet
.viewer .removed { background: #fdd; }
.viewer .added { background: #dfd; }
!Code
***/
//{{{
// Ensure that the DiffFormatterPlugin is only installed once.
if(!version.extensions.DiffFormatterPlugin) {
version.extensions.DiffFormatterPlugin = {installed:true};
if(version.major < 2 || (version.major == 2 && version.minor < 1)) {
alertAndThrow('DiffFormatterPlugin requires TiddlyWiki 2.1 or later.');
}
diffFormatter = {}; // 'namespace' for local functions
diffFormatter.init = function() {
var stylesheet = store.getTiddlerText(tiddler.title + "##StyleSheet");
if(stylesheet) { // check necessary because it happens more than once for some reason
config.shadowTiddlers["StyleSheetDiffFormatter"] = stylesheet;
store.addNotification("StyleSheetDiffFormatter", refreshStyles);
}
};
diffFormatter.added = {
name: 'diffAdded',
match: '^\\+',
termRegExp: /(\n)/mg,
handler: function(w)
{
var e = createTiddlyElement(w.output,'span',null,'added');
w.subWikifyTerm(e,this.termRegExp);
createTiddlyElement(w.output,'br');
}
};
diffFormatter.removed = {
name: 'diffRemoved',
match: '^-',
termRegExp: /(\n)/mg,
handler: function(w)
{
var e = createTiddlyElement(w.output,'span',null,'removed');
w.subWikifyTerm(e,this.termRegExp);
createTiddlyElement(w.output,'br');
}
};
diffFormatter.charDiff = {
name: 'diffChars',
match: '^(?:@@|[+-]{3}) ',
lookaheadRegExp: /^(?:@@|[+-]{3}) .*\n/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
};
// add new formatters
diffFormatter.init();
config.formatters.push(diffFormatter.added);
config.formatters.push(diffFormatter.removed);
diffFormatter.replaceFormatter = function()
{
for(var i=0; i<config.formatters.length; i++) {
if(config.formatters[i].name == 'characterFormat') {
config.formatters.splice(i,0,diffFormatter.charDiff);
break;
}
}
};
diffFormatter.replaceFormatter();
}// end of 'install only once'
//}}}
Background: #fff
Foreground: #000
PrimaryPale: #b63321
PrimaryLight: #b63321
PrimaryMid: #b63321
PrimaryDark: #b63321
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
<!--{{{-->
<!--<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>-->
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
This summer on August 2nd - 6th we'll be hosting a week long Young Rewired State event taking place at various venue's across the country. You'll have the chance to work with experts within their field and produce something great at the end of it.
If you are a 15-18 year old and interested in taking part please <<newTiddler label:"click here" title:"Your Name" template:EditRegTemplate
fields:"theme:register">>.
If you are a business and interested in taking part please <<newTiddler label:"click here" title:"Business" template:EditBizRegTemplate
fields:"theme:bizregister">>.
//Powered by [[TiddlyWiki|http://tiddlywiki.com]] and [[TiddlyWeb|http://tiddlyweb.com]]
/***
|Name|ListboxPlugin|
|Source|http://www.TiddlyTools.com/#ListboxPlugin|
|Documentation|http://www.TiddlyTools.com/#ListboxPluginInfo|
|Version|1.4.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|set custom field or tiddler tags by selecting from listbox/droplist|
The {{{<<select>>}}} macro allows you to set tiddler field values by selecting pre-configured values from a listbox/droplist control.
!!!!!Documentation
>see [[ListboxPluginInfo]]
!!!!!Revisions
<<<
2010.03.14 1.4.1 use filterTiddlers() instead of getTaggedTiddlers() - use MatchTagsPlugin for tag expressions
|please see [[ListboxPluginInfo]] for additional revision details|
2007.05.12 0.5.0 started
<<<
!!!!!Code
***/
//{{{
version.extensions.ListboxPlugin= {major: 1, minor: 4, revision: 1, date: new Date(2010,3,14)};
config.macros.select = {
tooltip: "select a value for %0@%1",
blankTooltip: "set %0@%1=[no value]",
valueTooltip: "set %0@%1=%2",
otherLabel: "other",
otherTooltip: "set %0@%1=[enter a value...]",
otherPrompt: "enter a value for '%0'",
editLabel: "edit list...",
editTooltip: "edit '%0' list definition (%1)",
changeMsg: "setting %0@%1=%2",
verbose: false,
hereKeyword: "here",
defaultTarget: "SiteFields",
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
// default to containing tiddler or "SiteFields" catch-all
var here=story.findContainingTiddler(place);
var targetID=here?here.getAttribute("tiddler"):this.defaultTarget;
// get field name and non-default target (if any)
var field=params.shift();
var pos=field.indexOf("@"); // if non-default target ("field@tiddler" syntax)
if(pos!=-1) { // split field into field and tiddlername.
if (field.substr(pos+1)!=this.hereKeyword) // "here" == use default target
targetID=field.substr(pos+1); // use different target tiddler
field=field.substr(0,pos);
}
if(!field || !field.length) return; // no field name... do nothing
if (field.substr(0,1)=="=") targetID="(system)"; // internal option value
var items=[]; var listsrc='';
var autosave=false; var allowBlank=false; var allowOther=false; var allowEdit=false;
var allowMultiple=false; var wikifyData=false; var rows=0; var width='';
var p=params.shift();
while (p) {
if (p.toLowerCase()=='autosave') // autosave on change
autosave=true;
else if (p.toLowerCase()=='allowblank') // add empty item
var allowBlank=true;
else if (p.toLowerCase()=='allowother') // add "other: ____" item
var allowOther=true;
else if (p.toLowerCase()=='allowedit') // add "edit list..." item
var allowEdit=true;
else if (p.toLowerCase()=='allowmultiple') // multi-select
var allowMultiple=true;
else if (p.startsWith('rows:')) // 0=autosize listbox, 1=droplist, n=listbox
var rows=p.substr(5);
else if (p.startsWith('width:')) // CSS width of list
var width=p.substr(6);
else if (p.startsWith('prompt:')) // prompt text (1st item in list)
var ptext=p.substr(7);
else if (p.substr(0,1)=="+"||p.substr(0,1)=="*") { // read HR-separated tiddler
var listsrc=p.substr(1);
var listtxt=store.getTiddlerText(listsrc,'');
var wikifyData=p.substr(0,1)=="*";
if (listtxt.length && wikifyData) // wikify source to handle macros/scripts
listtxt=this.getWikifiedData(listtxt);
if (listtxt.length)
items=items.concat(listtxt.split(listtxt.indexOf('\n----\n')!=-1?'\n----\n':'\n'));
}
else if (p.startsWith("=")) { // get items from tagged tiddlers
var filter=p.substr(1);
if (!filter.startsWith('[')) filter='[tag['+filter+']]';
var tids=store.filterTiddlers(filter);
for (var t=0; t<tids.length; t++) items.push(tids[t].title);
}
else { // param is item value or 'label=value'
var parts=p.split("=");
var label=parts[0]; var v=parts[1]?parts[1]:parts[0];
items.push(label+"="+v);
}
p=params.shift();
}
if (rows==1) allowMultiple=false; // droplist cannot do multi-select
if (tiddler && !story.isDirty(tiddler.title)) autosave=true; // tiddler is in VIEW mode, force autosave
this.render(createTiddlyElement(place,"span"), null,
targetID, field, ptext, items, listsrc, wikifyData,
rows, width, autosave, allowBlank, allowOther, allowEdit, allowMultiple);
store.addNotification(null,this.refresh); // syncs lists when tiddlers are changed
},
getWikifiedData: // wikify tiddler content, then extract text WITH newlines and HRs included
function(txt) {
var e=createTiddlyElement(document.body,"div"); wikify(txt,e);
var breaks=e.getElementsByTagName("br");
for (var b=0; b<breaks.length; b++) breaks[b].parentNode.insertBefore(document.createTextNode("\n"),breaks[b]);
var lines=e.getElementsByTagName("hr");
for (var l=0; l<lines.length; l++) lines[l].parentNode.insertBefore(document.createTextNode("----\n"),lines[l]);
var items=e.getElementsByTagName("li");
for (var i=0; i<items.length; i++) items[i].parentNode.insertBefore(document.createTextNode("\n"),items[i]);
var txt=getPlainText(e); removeNode(e); return txt;
},
refresh:
function (title) { // re-render dependent lists
var lists=document.getElementsByTagName('select');
for (var i=0; i<lists.length; i++) { var list=lists[i];
if (list.getAttribute('listsrc')!=title) continue; // no sync needed
var listtxt=store.getTiddlerText(list.getAttribute('listsrc')||'','');
if (listtxt.length && list.getAttribute("wikifyData")=="true")
listtxt=this.getWikifiedData(listtxt);
if (listtxt.length)
var items=listtxt.split(listtxt.indexOf('\n----\n')!=-1?'\n----\n':'\n');
config.macros.select.render(list.parentNode, list,
list.getAttribute('tiddler'),
list.getAttribute('edit'),
list.getAttribute('ptext'),
items||[],
list.getAttribute('listsrc'),
list.getAttribute("wikifyData")=="true",
list.getAttribute("rows"),
list.getAttribute("width"),
list.getAttribute("autosave")=="true",
list.getAttribute("allowBlank")=="true",
list.getAttribute("allowOther")=="true",
list.getAttribute("allowEdit")=="true",
list.getAttribute("allowMultiple")=="true");
}
},
render:
function (place, here, targetID, field, ptext, items, listsrc, wikifyData,
rows, width, autosave, allowBlank, allowOther, allowEdit, allowMultiple) {
var values=[]; var opts=[];
// use current selection(s) (if any) (except for "edit list..." item)
if (here) for (var i=0; i<here.options.length; i++) {
var opt=here.options[i];
if (opt.selected && opt.text!=config.macros.select.editLabel) values.push(opt.value);
}
// no listbox or no selections... get value(s) from field (if any)
if (!values.length) {
var v=(field.substr(0,1)=='=')?config.options[field.substr(1)]:store.getValue(targetID,field);
if (v) values=(field=='tags'||allowMultiple)?v.readBracketedList():[v];
}
// add prompt item
if (ptext&&ptext.length)
opts.push('<option value="_ptext" title="">'+ptext+'</option>');
// add 'no value' item
if ((!allowMultiple && !values.length) || allowBlank)
opts.push('<option value="" title="'+this.blankTooltip.format([field,targetID])+'"></option>');
// add enumerated items
var isOther=values.length; // assume no matching value
for (var opt=0; opt<items.length; opt++) {
var lines=items[opt].split("\n"); var parts=lines[0].split("=");
var label=parts[0];
var v=parts[1]?parts[1]:parts[0];
var title=lines[1]?lines[1]:this.valueTooltip.format([field,targetID,v]);
var sel=values.contains(v); if (sel) isOther=false; // found matching value
opts.push('<option value="'+v+'" '+(sel?'selected':'')+' title="'+title+'">'+label+'</option>');
}
// add 'other...'
if (field=='tags') isOther=false;
if (isOther||allowOther) {
var label="other"+(isOther?(": "+values[0]):"...");
var v=isOther?values[0]:'';
var t=this.otherTooltip.format([field,targetID]);
opts.push('<option value="'+v+'" '+(isOther?'selected':'')+' title="'+t+'">'+label+'</option>');
}
// add 'edit list...'
if (listsrc && (!store.getTiddlerText(listsrc) || allowEdit)) {
var title=this.editTooltip.format([field,listsrc]);
opts.push('<option value="'+listsrc+'" title="'+title+'">'+this.editLabel+'</option>');
}
// render listbox
var html='<select '+(values[0]?'value="'+values[0]+'" ':' ')
+' title="'+this.tooltip.format([field,targetID])+'"'
+' rows="'+rows+'"'+' size="'+(rows!=0?rows:opts.length)+'"'+' style="width:'+width+'"'
+' tiddler="'+targetID+'"'+' edit="'+field+'"'+' ptext="'+ptext+'"'
+' listsrc="'+listsrc+'"'+' wikifyData="'+wikifyData+'"'
+' autosave="'+autosave+'"'+' allowBlank="'+allowBlank+'"'+' allowOther="'+allowOther+'"'
+' allowEdit="'+allowEdit+'"'+' allowMultiple="'+allowMultiple+'"'+(allowMultiple?' multiple':'')
+' onclick="return config.macros.select.onClick(this,event)"'
+' onchange="return config.macros.select.onChange(this,event)"'
+' ondblclick="return false">'+opts.join('')+'</select>';
place.innerHTML=html;
},
onClick:
function(here,event) {
var sel=here.selectedIndex;
if (sel!=-1 && here.options[sel].text.startsWith(config.macros.select.otherLabel))
here.onchange.apply(here,arguments);
},
onChange:
function(here,event) {
var cms=config.macros.select; // abbrev
var sel=here.selectedIndex;
if (sel!=-1) {
if (here.options[sel].text==cms.editLabel) {
story.displayTiddler(story.findContainingTiddler(here),here.value,DEFAULT_EDIT_TEMPLATE);
return false;
}
if (here.options[sel].text.startsWith(cms.otherLabel)) {
var newval=prompt(cms.otherPrompt.format([here.getAttribute("edit")]),here.value);
if (!newval) {// user cancelled
var v=store.getValue(here.getAttribute("tiddler"),here.getAttribute("edit"));
{ here.value=v; if (v==undefined) here.selectedIndex=0; return false; }
};
here.options[sel].value=newval;
here.options[sel].text=cms.otherLabel+": "+newval;
here.value=newval;
}
if (here.options[sel].value=='_ptext')
for (var i=0; i<here.options.length; i++)
here.options[i].selected=false;
}
if (here.getAttribute("autosave")=="true") config.macros.select.setFieldValue(here);
return false;
},
setFieldValue: function(here) {
var tid=here.getAttribute("tiddler"); if (!tid || !tid.length) return; // no target, do nothing
var field=here.getAttribute("edit");
if (field.substr(0,1)=='=') { // option cookie instead of tiddler field
config.macros.option.propagateOption(field.substr(1),"value",here.value,"input");
return;
}
// ensure tiddler exists
if (!store.tiddlerExists(tid)) store.saveTiddler(tid,tid,"",config.options.txtUserName,new Date(),[]);
if (field=='tags') {
store.suspendNotifications();
for (var i=0; i<here.options.length; i++) {
var opt=here.options[i];
if (opt.text==config.macros.select.editLabel) continue;
store.setTiddlerTag(tid,opt.selected,opt.value);
}
store.resumeNotifications();
} else {
// get multi-select items
var values=[];
for (var i=0; i<here.options.length; i++) {
var opt=here.options[i];
if (opt.text==config.macros.select.editLabel) continue;
if (opt.selected) values.pushUnique(String.encodeTiddlyLink(opt.value));
}
if (values.length==1) values=[here.value]; // remove unneeded brackets around single value
store.setValue(tid,field,values.length?values.join(' '):null); // if no selections, delete field
}
// 'touch' tiddler and report to user
var t=store.getTiddler(tid);
var who=config.options.chkForceMinorUpdate?t.modifier:config.options.txtUserName;
var when=config.options.chkForceMinorUpdate?t.modified:new Date();
store.saveTiddler(tid,tid,t.body,who,when,t.tags,t.fields);
if (config.macros.select.verbose)
{ clearMessage(); displayMessage(config.macros.select.changeMsg.format([field,tid,here.value])); }
}
}
//}}}
<!--{{{-->
<!--<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>-->
<div class='title' macro='view title'></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer'>
<h2>About your company</h2>
<span class='nl' macro='view business wikified'>business: </span>
<span class='nl' macro='view url wikified'>url: </span>
<span class='nl' macro='view number_of_spaces wikified'>number_of_spaces: </span>
<span class='nl' macro='view map wikified'>map: </span>
<h2>Contact information</h2>
<span class='nl' macro='view contact_name wikified'>contact_name: </span>
<span class='nl' macro='view email wikified'>email: </span>
<span class='nl' macro='view tel_num wikified'>tel_num: </span>
<span class='nl' macro='view add1 wikified'>add1: </span>
<span class='nl' macro='view add2 wikified'>add2: </span>
<span class='nl' macro='view add3 wikified'>add3: </span>
<span class='nl' macro='view add4 wikified'>add4: </span>
<span class='nl' macro='view postcode wikified'>postcode: </span>
</div>
<div class='title' macro='tiddler RegistrationComplete'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<h2 class="title">Register Your Interest</h2>
<div class='edit-bag' macro="edit 'server.workspace' 0 'bags/registered' "></div>
<h3>Who are you?</h3>
Full name<div class='editor simple-editor reg-title' macro='edit title'></div>
email<span class='editor simple-editor' macro='edit email'></span>
Telephone number<span class='editor simple-editor' macro='edit telephone_num'></span>
Date of Birth<span class='editor simple-editor' macro='edit dob'></span>
School/Organisation<span class='editor simple-editor' macro='edit school'></span>
Which location is best for you<span class='editor simple-editor' macro='edit location'></span>
<h3>A bit about you...</h3>
Tell us about your level of experience, if you could point to anything you've built that'd be great!<span class='editor free-editor' macro='edit
text'></span>
Why would you like to get involved in Young Rewired State<span class='editor free-editor' macro='edit reason_why'></span>
Have you participated in a Young Rewired State event before?<span class='editor free-editor' macro='edit first_time'></span>
<div class='toolbar register-toolbar' macro='toolbar [[ToolbarCommands::RegisterToolbar]]'></div>
<!--}}}-->
/*
BetterListPlugin
*/
/***
|Name|BetterListPlugin|
|Description||
|Source||
|Documentation||
|Version|0.1|
|Author|Michael Mahemoff, Osmosoft|
|''License:''|[[BSD open source license]]|
|~CoreVersion|2.2|
***/
(function($) {
version.extensions.BetterListPlugin = {installed:true};
var macro = config.macros.betterList = {
init: function() {
// var stylesheet = store.getTiddlerText(tiddler.title + "##StyleSheet");
// config.shadowTiddlers["StyleSheetBetterListPlugin"] = stylesheet;
// store.addNotification("StyleSheetBetterListPlugin", refreshStyles);
},
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var macroParams = paramString.parseParams();
var type = params[0] || "all";
$(place).addClass("betterList");
if (!config.macros.list[type].handler) return;
var tiddlers = config.macros.list[type].handler(params);
if (tiddlers.length) {
var $list = $("<ul/>").appendTo(place);
$.each(tiddlers, function(i, tiddler) {
var $li = $("<li/>").appendTo($list);
createTiddlyLink($li.get(0), tiddler.title || tiddler, true);
});
} else {
$("<div/>").text(getParam(macroParams, "emptyMessage") || "no matches").appendTo(place);
}
}
}
})(jQuery);
/***
!StyleSheet
!(end of StyleSheet)
***/
/*}}}*/
<!--{{{-->
<h2 class="title">Register your interest</h2>
<div class='edit-bag' macro="edit 'server.workspace' 0 'bags/registered' "></div>
<h3>About your company</h3>
Business name<div class='editor simple-editor reg-title' macro='edit business'></div>
URL<div class='editor simple-editor reg-title' macro='edit url'></div>
Number of spaces available for YRSers <div class='editor simple-editor reg-title' macro='edit number_of_spaces'></div>
Are you happy for you company to appear on the Rewired State map? <div class='editor simple-editor reg-title' macro='edit map'></div>
Any additional information you'd like to tell us?<span class='editor free-editor' macro='edit text'></span>
<h3>Contact information</h3>
Contact name <div class='editor simple-editor reg-title' macro='edit contact_name'></div>
email<span class='editor simple-editor' macro='edit email'></span>
Telephone number<span class='editor simple-editor' macro='edit tel_num'></span>
Address line 1<span class='editor simple-editor' macro='edit add1'></span>
Address line 2<span class='editor simple-editor' macro='edit add2'></span>
Address line 3<span class='editor simple-editor' macro='edit add3'></span>
Address line 4<span class='editor simple-editor' macro='edit add4'></span>
Postcode<span class='editor simple-editor' macro='edit postcode'></span>
<div class='toolbar register-toolbar' macro='toolbar [[ToolbarCommands::RegisterToolbar]]'></div>
<!--}}}-->
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
/***
|Name|EditFieldPlugin|
|Source|http://www.TiddlyTools.com/#EditFieldPlugin|
|Version|1.5.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|extend core edit macro for use in ViewTemplates or direct embedding in tiddler content|
!!!!!Usage
<<<
Normally, when a tiddler is edited, a set of input fields is displayed (as defined by the [[EditTemplate]]), and any changes you make are only saved when you press the "done" (or "cancel") command in the tiddler editor's toolbar. However, you can also ''embed an input field directly in //viewed// tiddler content'' by writing:
{{{
<<edit fieldname numberOfLines defaultValue>>
<<edit fieldname@TiddlerName numberOfLines defaultValue>>
}}}
or in the [[ViewTemplate]] (to add it to every tiddler):
{{{
<span macro='edit fieldname numberOfLines defaultValue'></span>
<span macro='edit fieldname@TiddlerName numberOfLines defaultValue'></span>
}}}
Unfortunately, while the input field will be displayed, the "done" command item is not available when //viewing// a tiddler, so the 'save/discard' handling cannot be invoked once you have decided that your input activities are complete, and any changes you make will not stored anywhere. To address this, the plugin extends the input field handler so that when a field is embedded in normal tiddler content and you make changes, it can automatically save/discard your changes as soon as you press ENTER or move away ('onBlur' handling) from that input field. You can also abandon your changes to input field content by pressing ESCAPE.
The plugin also adds support for an optional 'remote field reference' syntax: "{{{fieldname@TiddlerName}}}" so you can display and edit fields stored in other tiddlers. This allows you to create, for example, 'summary' tiddlers for reviewing/editing field values from several tiddlers at the same time. Note: whenever a remote field reference is used (even within the [[EditTemplate]]), the automatic save/discard behavior described above will be applied to that field, so that any changes will be saved immediately, and will not be saved again when the "done" command is pressed.
<<<
!!!!!Examples
<<<
*"""<<edit foobar>>"""<br><<edit foobar>>
*"""<<edit foobar@SomeTiddler>>"""<br><<edit foobar@SomeTiddler>>
*"""<<edit tags>>"""<br><<edit tags>>
*"""<<edit text 15>>"""<br>{{editor{<<edit text 15>>}}}
<<<
!!!!!Revisions
<<<
2009.09.16 [1.5.1] fixed 'onblur' handling for local fields (fieldname@here). Added support for '@here' syntax
2009.09.05 [1.5.0] code refactored. added handling for fieldname@tiddlername
2007.08.22 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.EditFieldPlugin= {major: 1, minor: 5, revision: 1, date: new Date(2009,9,16)};
config.macros.edit.editFieldPlugin_savedHandler=config.macros.edit.handler;
config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// let core render input/textarea, then get resulting element
config.macros.edit.editFieldPlugin_savedHandler.apply(this,arguments);
var fieldType=params[0]=="text"||params[1]?'textarea':'input';
var elems=place.getElementsByTagName(fieldType); var e=elems[elems.length-1];
// extended fieldname@tiddlername handling
var parts=e.getAttribute("edit").split('@');
var field=parts[0];
var title=parts[1]||tiddler.title;
if (title=='here') title=tiddler.title;
// stop field from being saved with 'done' button
if (parts[1]) { e.setAttribute("edit",null); e.setAttribute("field",field); }
// save starting value and target tiddler
e.setAttribute("currval",store.getValue(title,field)||''); // save starting value
e.setAttribute("tiddler",title);
// force height for textarea field
if (fieldType=="textarea" && params[1]) e.style.height=params[1]+"em";
// if viewing tiddler, add autosave handlers
var here=story.findContainingTiddler(place);
var isViewed=here&&here.getAttribute("template").indexOf("ViewTemplate")!=-1;
if (parts[1]||isViewed) { // remote reference or view mode editing...
story.setDirty(tiddler.title,false); // clear tiddler ("dirty") flag (set by core)
e.onkeydown=function(ev) { // ENTER key=save (for single-line input)
var event=ev?ev:window.event;
this.setAttribute("keyCode",event.keyCode); // save last keyCode (for blur)
if (event.keyCode==13 && this.nodeName.toUpperCase()!="TEXTAREA")
this.saveField(); // save input to tiddler field
}
e.onblur=function(ev) { // confirm input when focus moves away
var event=ev?ev:window.event;
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit")||this.getAttribute("field");
if (this.value==this.getAttribute("currval")) return; // no change
if (this.getAttribute("keyCode")=="27") { // if user pressed ESC
var msg="Abandon changes to %0@%1?".format([field,tid]);
if (confirm(msg)) this.value=this.getAttribute("currval"); // reset value
this.id=new Date().getTime(); // set unique ID for delayed re-focus after blur
setTimeout("document.getElementById('"+this.id+"').focus()",1);
} else { // other focus change events
var msg="Save changes to %0@%1?".format([field,tid]);
if (confirm(msg)) this.saveField();
else this.value=this.getAttribute("currval");
}
};
e.saveField=function() { // unpack/validate attribs and then save the field
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit")||this.getAttribute("field");
var title=(field=="title")?this.value:tid;
if (!title.length) { // error: blank tiddler title
this.value=this.getAttribute("currval"); // reset value
this.id=new Date().getTime(); // set unique ID for delayed messages/refocus
setTimeout("displayMessage('Please enter a non-blank value')",1);
setTimeout("document.getElementById('"+this.id+"').focus()",2);
return;
}
config.macros.edit.saveField(tid,title,field,this.value);
this.setAttribute("currval",this.value); // remember new starting value
};
}
}
//}}}
//{{{
// save input value to tiddler field (create/touch/rename tiddler as needed)
config.macros.edit.saveField = function(tid,title,field,val) {
var t=store.getTiddler(tid);
store.suspendNotifications();
var anim=config.options.chkAnimate; config.options.chkAnimate=false; // suspend animation
var who=t&&config.options.chkForceMinorUpdate?t.modifier:config.options.txtUserName;
var when=t&&config.options.chkForceMinorUpdate?t.modified:new Date();
store.saveTiddler(t?tid:title,title,t?t.text:"",who,when,t?t.tags:[],t?t.fields:null);
store.setValue(title,field,val); // save field
if (tid!=title) // new title... show renamed tiddler in place of current one
{ story.displayTiddler(story.getTiddler(tid),title); story.closeTiddler(tid); }
if (field=="text") // content changed, refresh tiddler display
{ story.refreshTiddler(title,null,true); }
config.options.chkAnimate=anim; // resume animation
store.resumeNotifications();
store.notify(title,true);
}
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
/***
|''Name''|RadioButtonMacro|
|''Description''|macro to generate radio button elements|
|''Author''|FND|
|''Version''|0.1.0|
|''Status''|@@experimental@@|
|''Source''|http://svn.tiddlywiki.org/Trunk/contributors/FND/plugins/RadioButtonMacro.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Keywords''|forms|
!Usage
{{{
<<radio label value1 value2 [value3 value4 ... ]>>
}}}
!!Examples
<<radio "Sample Selection" foo bar baz>>
!Revision History
!!v0.1 (2010-03-18)
* initial release
!To Do
* persistence
* selection initialization
!Code
***/
//{{{
(function($) {
config.macros.radio = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var label = params.shift();
var group = label.replace(/\s/g, "_");
var container = $("<fieldset />");
$("<legend />").text(label).appendTo(container);
$.each(params, function(i, item) {
var radio = $('<input type="radio" />').
attr("name", group).val(item);
container.append(radio).append(item);
});
$("<form />").append(container).appendTo(place);
}
};
})(jQuery);
//}}}
/***
|''Name''|TiddlyWebConfig|
|''Description''|configuration settings for TiddlyWebWiki|
|''Author''|FND|
|''Version''|0.7.4|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/TiddlyWebConfig.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Requires''|TiddlyWebAdaptor|
|''Keywords''|serverSide TiddlyWeb|
!Revision History
!!v0.1 (2008-11-30)
* initial release
!!v0.2 (2009-01-15)
* removed obsolete dependencies
!!v0.3 (2009-03-16)
* sync username with server
!!v0.4 (2009-05-23)
* cache list of available login challengers
!!v0.5 (2009-07-10)
* disabled save and delete toolbar commands for unauthorized users
!!v0.6 (2009-08-15)
* disabled edit toolbar command for unauthorized users
!!v0.7 (2009-09-11)
* added revisions toolbar command
!Code
***/
//{{{
if(!config.adaptors.tiddlyweb) {
throw "Missing dependency: TiddlyWebAdaptor";
}
(function() {
if(window.location.protocol != "file:") {
config.options.chkAutoSave = true;
}
// initialize configuration
var adaptor = tiddler.getAdaptor();
var host = tiddler.fields["server.host"];
var recipe = tiddler.fields["server.recipe"];
var workspace = recipe ? "recipes/" + recipe : "bags/common";
config.defaultCustomFields = {
"server.type": tiddler.getServerType(),
"server.host": host,
"server.workspace": workspace
};
// modify toolbar commands
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.
replace("closeTiddler ", "revisions closeTiddler ");
config.commands.saveTiddler.isEnabled = function(tiddler) {
return hasPermission("write", tiddler);
};
config.commands.deleteTiddler.isEnabled = function(tiddler) {
return hasPermission("delete", tiddler);
};
// hijack Tiddler.prototype.isReadOnly to use permissions
var original = Tiddler.prototype.isReadOnly;
Tiddler.prototype.isReadOnly = function() {
var readOnly = original.apply(this, arguments); // global read-only mode
return readOnly || !hasPermission("write", this);
};
var hasPermission = function(type, tiddler) {
var perms = tiddler.fields["server.permissions"];
if(perms) {
return perms.split(", ").contains(type);
} else {
return true;
}
};
// retrieve server info
var statusCallback = function(context, userParams) {
if(context.serverStatus) {
// set username
if(context.serverStatus.username) {
config.macros.option.propagateOption("txtUserName",
"value", context.serverStatus.username, "input");
}
// retrieve challengers
if(context.serverStatus.challengers) {
config.adaptors.tiddlyweb.challengers = context.serverStatus.challengers;
}
}
};
adaptor.getStatus({ host: host }, null, statusCallback);
})();
//}}}
/***
|''Name:''|ThemedTiddlerPlugin |
|''Description:''|Per-Tiddler Mini-Themes |
|''Author:''|PaulDowney (psd (at) osmosoft (dot) com) |
|''Source:''|http://whatfettle.com/2008/07/ThemedTiddlerPlugin/ |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/PaulDowney/plugins/ThemedTiddlerPlugin/ |
|''Version:''|0.1|
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''~CoreVersion:''|2.4|
!!Documentation
The extended field "theme" is used to reference a tiddler containing a "mini-theme"
A mini-theme is a tiddler containing a [[ViewTemplate]], [[EditTemplate]] and [[StyleSheet]] sections which are applied when the tiddler is displayed.
In addition, a CSS class of the theme name is added to the tiddler which may be useful when writing a mini-theme [[StyleSheet]].
!!Code
***/
//{{{
/*jslint onevar: false nomen: false plusplus: false */
/*global Story, store, setStylesheet, addClass */
if (!version.extensions.ThemedTiddlerPlugin) {
version.extensions.ThemedTiddlerPlugin = {installed: true};
Story.prototype.__chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler;
Story.prototype.chooseTemplateForTiddler = function (title, n)
{
// translate number into template name
var template = ["ViewTemplate", "EditTemplate"][n ? n - 1 : 0];
var tiddler = store.getTiddler(title);
if (tiddler) {
var theme = tiddler.fields.theme;
if (theme) {
// assert stylesheet
var style = store.getTiddlerText(theme + '##StyleSheet');
if (style) {
setStylesheet(style, theme);
}
// return theme template
var slice = theme + '##' + template;
if (store.getTiddlerText(slice)) {
return slice;
}
}
}
// default template
return this.__chooseTemplateForTiddler.apply(this, arguments);
};
// assert theme name as a class on the tiddler
Story.prototype.__refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function (title, template, force, customFields, defaultText)
{
var tiddlerElem = this.__refreshTiddler.apply(this, arguments);
var tiddler = store.getTiddler(title);
if (tiddler) {
addClass(tiddlerElem, store.getTiddler(title).fields.theme);
}
return tiddlerElem;
};
}
//}}}
/***
|''Name''|TiddlyWebAdaptor|
|''Description''|adaptor for interacting with TiddlyWeb|
|''Author:''|FND|
|''Contributors''|Chris Dent, Martin Budden|
|''Version''|1.0.0|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/adaptors/TiddlyWebAdaptor.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5|
|''Keywords''|serverSide TiddlyWeb|
!Notes
This plugin includes [[jQuery JSON|http://code.google.com/p/jquery-json/]].
!To Do
* createWorkspace
* document custom/optional context attributes (e.g. filters, query, revision) and tiddler fields (e.g. server.title, origin)
!Code
***/
//{{{
(function($) {
var adaptor;
adaptor = config.adaptors.tiddlyweb = function() {}; //# set up alias
adaptor.prototype = new AdaptorBase();
adaptor.serverType = "tiddlyweb";
adaptor.serverLabel = "TiddlyWeb";
adaptor.mimeType = "application/json";
adaptor.parsingErrorMessage = "Error parsing result from server";
adaptor.locationIDErrorMessage = "no bag or recipe specified for tiddler"; // TODO: rename
// retrieve current status (requires TiddlyWeb status plugin)
adaptor.prototype.getStatus = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/status";
var uri = uriTemplate.format([context.host]);
var req = httpReq("GET", uri, adaptor.getStatusCallback, context,
null, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getStatusCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.serverStatus = $.evalJSON(responseText); // XXX: error handling!?
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve a list of workspaces
adaptor.prototype.getWorkspaceList = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.workspaces = [];
var uriTemplate = "%0/recipes"; // XXX: bags?
var uri = uriTemplate.format([context.host]);
var req = httpReq("GET", uri, adaptor.getWorkspaceListCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getWorkspaceListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
try {
var workspaces = $.evalJSON(responseText);
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
context.workspaces = workspaces.map(function(itm) { return { title: itm }; });
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve a list of tiddlers
adaptor.prototype.getTiddlerList = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers%3";
var params = context.filters ? "?filter=" + context.filters : "";
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), params]);
var req = httpReq("GET", uri, adaptor.getTiddlerListCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.tiddlers = [];
try {
var tiddlers = $.evalJSON(responseText); //# N.B.: not actual tiddler instances
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
for(var i = 0; i < tiddlers.length; i++) {
var t = tiddlers[i];
var tiddler = new Tiddler(t.title);
tiddler.assign(t.title, null, t.modifier, t.modified, t.tags, t.created, t.fields);
tiddler.fields["server.workspace"] = "bags/" + t.bag;
tiddler.fields["server.page.revision"] = t.revision;
context.tiddlers.push(tiddler);
}
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// perform global search
adaptor.prototype.getSearchResults = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/search?q=%1%2";
var filterString = context.filters ? ";filter=" + context.filters : "";
var uri = uriTemplate.format([context.host, context.query, filterString]); // XXX: parameters need escaping?
var req = httpReq("GET", uri, adaptor.getSearchResultsCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getSearchResultsCallback = function(status, context, responseText, uri, xhr) {
adaptor.getTiddlerListCallback(status, context, responseText, uri, xhr); // XXX: use apply?
};
// retrieve a particular tiddler's revisions
adaptor.prototype.getTiddlerRevisionList = function(title, limit, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions";
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title)]);
var req = httpReq("GET", uri, adaptor.getTiddlerRevisionListCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerRevisionListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.revisions = [];
try {
var tiddlers = $.evalJSON(responseText); //# N.B.: not actual tiddler instances
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
for(var i = 0; i < tiddlers.length; i++) {
var t = tiddlers[i];
var tiddler = new Tiddler(t.title);
tiddler.assign(t.title, null, t.modifier, Date.convertFromYYYYMMDDHHMM(t.modified),
t.tags, Date.convertFromYYYYMMDDHHMM(t.created), t.fields);
tiddler.fields["server.type"] = adaptor.serverType;
tiddler.fields["server.host"] = AdaptorBase.minHostName(context.host);
tiddler.fields["server.page.revision"] = t.revision;
tiddler.fields["server.workspace"] = "bags/" + t.bag;
context.revisions.push(tiddler);
}
var sortField = "server.page.revision";
context.revisions.sort(function(a, b) {
return a.fields[sortField] < b.fields[sortField] ? 1 :
(a.fields[sortField] == b.fields[sortField] ? 0 : -1);
});
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve an individual tiddler revision -- XXX: breaks with standard arguments list -- XXX: convenience function; simply use getTiddler?
adaptor.prototype.getTiddlerRevision = function(title, revision, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.revision = revision;
return this.getTiddler(title, context, userParams, callback);
};
// retrieve an individual tiddler
//# context is an object with members host and workspace
//# callback is passed the new context and userParams
adaptor.prototype.getTiddler = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
if(context.revision) {
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions/%4";
} else {
uriTemplate = "%0/%1/%2/tiddlers/%3";
}
if(!context.tiddler) {
context.tiddler = new Tiddler(title);
}
context.tiddler.fields["server.type"] = adaptor.serverType;
context.tiddler.fields["server.host"] = AdaptorBase.minHostName(context.host);
context.tiddler.fields["server.title"] = title; //# required for detecting renames
context.tiddler.fields["server.workspace"] = context.workspace;
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title),
context.revision]);
var req = httpReq("GET", uri, adaptor.getTiddlerCallback, context,
{ accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
try {
var t = $.evalJSON(responseText); //# N.B.: not an actual tiddler instance
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
context.tiddler.assign(context.tiddler.title, t.text, t.modifier,
Date.convertFromYYYYMMDDHHMM(t.modified), t.tags || [],
Date.convertFromYYYYMMDDHHMM(t.created), context.tiddler.fields); // XXX: merge extended fields!?
context.tiddler.fields["server.workspace"] = t.bag ? "bags/" + t.bag : "recipes/" + t.recipe; // XXX: bag is always supplied!?
context.tiddler.fields["server.page.revision"] = t.revision;
context.tiddler.fields["server.permissions"] = t.permissions.join(", ");
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve tiddler chronicle (all revisions)
adaptor.prototype.getTiddlerChronicle = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions?fat=1";
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title)]);
var req = httpReq("GET", uri, adaptor.getTiddlerChronicleCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerChronicleCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.responseText = responseText;
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// store an individual tiddler
adaptor.prototype.putTiddler = function(tiddler, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = tiddler.title;
context.tiddler = tiddler;
context.host = context.host || this.fullHostName(tiddler.fields["server.host"]);
if(!tiddler.fields["server.title"]) {
tiddler.fields["server.title"] = tiddler.title; //# required for detecting subsequent renames
} else if(tiddler.title != tiddler.fields["server.title"]) {
return this.moveTiddler({ title: tiddler.fields["server.title"] },
{ title: tiddler.title }, context, userParams, callback);
}
var uriTemplate = "%0/%1/%2/tiddlers/%3";
try {
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
} catch(ex) {
return adaptor.locationIDErrorMessage;
}
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title)]);
var etag = adaptor.generateETag(workspace, tiddler);
var headers = etag ? { "If-Match": '"' + etag + '"' } : null;
var payload = {
title: tiddler.title,
text: tiddler.text,
modifier: tiddler.modifier,
tags: tiddler.tags,
fields: $.extend({}, tiddler.fields)
};
delete payload.fields.changecount;
payload = $.toJSON(payload);
var req = httpReq("PUT", uri, adaptor.putTiddlerCallback,
context, headers, payload, adaptor.mimeType, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.status) {
context.adaptor.getTiddler(context.tiddler.title, context);
} else if(context.callback) {
context.callback(context, context.userParams);
}
};
// store a tiddler chronicle
adaptor.prototype.putTiddlerChronicle = function(revisions, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = revisions[0].title;
var headers = null;
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions";
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(context.title)]);
if(workspace.type == "bag") { // generate ETag
var etag = [adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(context.title), 0].join("/"); //# zero-revision prevents overwriting existing contents
headers = { "If-Match": '"' + etag + '"' };
}
var payload = $.toJSON(revisions);
var req = httpReq("POST", uri, adaptor.putTiddlerChronicleCallback,
context, headers, payload, adaptor.mimeType, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerChronicleCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// store a collection of tiddlers (import TiddlyWiki HTML store)
adaptor.prototype.putTiddlerStore = function(store, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers";
var host = context.host;
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name)]);
var req = httpReq("POST", uri, adaptor.putTiddlerStoreCallback,
context, null, store, "text/x-tiddlywiki", null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerStoreCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// rename an individual tiddler or move it to a different workspace -- TODO: make {from|to}.title optional
//# from and to are objects with members title and workspace (bag; optional),
//# representing source and target tiddler, respectively
adaptor.prototype.moveTiddler = function(from, to, context, userParams, callback) { // XXX: rename parameters (old/new)?
var _this = this;
var newTiddler = store.getTiddler(from.title) || store.getTiddler(to.title); //# local rename might already have occurred
var oldTiddler = $.extend(true, {}, newTiddler); //# required for eventual deletion
oldTiddler.title = from.title; //# required for original tiddler's ETag
var _getTiddlerChronicle = function(title, context, userParams, callback) {
return _this.getTiddlerChronicle(title, context, userParams, callback);
};
var _putTiddlerChronicle = function(context, userParams) {
if(!context.status) {
return callback(context, userParams);
}
var revisions = $.evalJSON(context.responseText); // XXX: error handling?
// change current title while retaining previous location
for(var i = 0; i < revisions.length; i++) {
if(!revisions[i].fields.origin) { // N.B.: origin = "<workspace>/<title>"
revisions[i].fields.origin = ["bags", revisions[i].bag, revisions[i].title].join("/");
}
revisions[i].title = to.title;
}
// add new revision
var rev = $.extend({}, revisions[0]);
rev.title = to.title;
$.each(newTiddler, function(i, item) {
if(!$.isFunction(item)) {
rev[i] = item;
}
});
rev.revision++;
rev.created = rev.created.convertToYYYYMMDDHHMM();
rev.modified = new Date().convertToYYYYMMDDHHMM();
delete rev.fields.changecount;
revisions.unshift(rev);
if(to.workspace) {
context.workspace = to.workspace;
} else if(context.workspace.substring(0, 4) != "bags") { // N.B.: target workspace must be a bag
context.workspace = "bags/" + rev.bag;
}
var subCallback = function(context, userparams) {
var rev = "server.page.revision";
newTiddler.fields[rev] = parseInt(newTiddler.fields[rev], 10) + 1; // XXX: extended fields' values should be strings!?
newTiddler.fields["server.title"] = to.title;
_deleteTiddler(context, userparams);
};
return _this.putTiddlerChronicle(revisions, context, context.userParams, subCallback);
};
var _deleteTiddler = function(context, userParams) {
if(!context.status) {
return callback(context, userParams);
}
context.callback = null;
return _this.deleteTiddler(oldTiddler, context, context.userParams, callback);
};
callback = callback || function() {};
context = this.setContext(context, userParams);
context.workspace = from.workspace || oldTiddler.fields["server.workspace"];
return _getTiddlerChronicle(from.title, context, userParams, _putTiddlerChronicle);
};
// delete an individual tiddler
adaptor.prototype.deleteTiddler = function(tiddler, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = tiddler.title; // XXX: not required!?
var uriTemplate = "%0/%1/%2/tiddlers/%3";
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
try {
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
} catch(ex) {
return adaptor.locationIDErrorMessage;
}
var uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title)]);
var etag = adaptor.generateETag(workspace, tiddler);
var headers = etag ? { "If-Match": '"' + etag + '"' } : null;
var req = httpReq("DELETE", uri, adaptor.deleteTiddlerCallback, context, headers,
null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.deleteTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// compare two revisions of a tiddler (requires TiddlyWeb differ plugin)
//# if context.rev1 is not specified, the latest revision will be used for comparison
//# if context.rev2 is not specified, the local revision will be sent for comparison
//# context.format is a string as determined by the TiddlyWeb differ plugin
adaptor.prototype.getTiddlerDiff = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
var tiddler = store.getTiddler(title);
try {
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
} catch(ex) {
return adaptor.locationIDErrorMessage;
}
var tiddlerRef = [workspace.type + "s", workspace.name, tiddler.title].join("/");
var rev1 = context.rev1 ? [tiddlerRef, context.rev1].join("/") : tiddlerRef;
var rev2 = context.rev2 ? [tiddlerRef, context.rev2].join("/") : null;
var uriTemplate = "%0/diff?rev1=%1";
if(rev2) {
uriTemplate += "&rev2=%2";
}
if(context.format) {
uriTemplate += "&format=%3";
}
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var uri = uriTemplate.format([host, adaptor.normalizeTitle(rev1),
adaptor.normalizeTitle(rev2), context.format]);
if(rev2) {
var req = httpReq("GET", uri, adaptor.getTiddlerDiffCallback, context, null,
null, null, null, null, true);
} else {
var payload = {
title: tiddler.title,
text: tiddler.text,
modifier: tiddler.modifier,
tags: tiddler.tags,
fields: $.extend({}, tiddler.fields)
}; // XXX: missing attributes!?
payload = $.toJSON(payload);
req = httpReq("POST", uri, adaptor.getTiddlerDiffCallback, context,
null, payload, adaptor.mimeType, null, null, true);
}
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerDiffCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.diff = responseText;
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// generate tiddler information
adaptor.prototype.generateTiddlerInfo = function(tiddler) {
var info = {};
var uriTemplate = "%0/%1/%2/tiddlers/%3";
var host = this.host || tiddler.fields["server.host"]; // XXX: this.host obsolete?
host = this.fullHostName(host);
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
info.uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title)]);
return info;
};
adaptor.resolveWorkspace = function(workspace) {
var components = workspace.split("/");
return {
type: components[0] == "bags" ? "bag" : "recipe",
name: components[1] || components[0]
};
};
adaptor.generateETag = function(workspace, tiddler) {
var etag = null;
if(workspace.type == "bag") {
var revision = tiddler.fields["server.page.revision"];
if(typeof revision == "undefined") {
revision = "0";
}
etag = [adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title), revision].join("/");
}
return etag;
};
adaptor.normalizeTitle = function(title) {
return encodeURIComponent(title);
};
})(jQuery);
/*
* jQuery JSON Plugin
* version: 1.3
* source: http://code.google.com/p/jquery-json/
* license: MIT (http://www.opensource.org/licenses/mit-license.php)
*/
(function($){function toIntegersAtLease(n)
{return n<10?'0'+n:n;}
Date.prototype.toJSON=function(date)
{return this.getUTCFullYear()+'-'+
toIntegersAtLease(this.getUTCMonth())+'-'+
toIntegersAtLease(this.getUTCDate());};var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};$.quoteString=function(string)
{if(escapeable.test(string))
{return'"'+string.replace(escapeable,function(a)
{var c=meta[a];if(typeof c==='string'){return c;}
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};$.toJSON=function(o,compact)
{var type=typeof(o);if(type=="undefined")
return"undefined";else if(type=="number"||type=="boolean")
return o+"";else if(o===null)
return"null";if(type=="string")
{return $.quoteString(o);}
if(type=="object"&&typeof o.toJSON=="function")
return o.toJSON(compact);if(type!="function"&&typeof(o.length)=="number")
{var ret=[];for(var i=0;i<o.length;i++){ret.push($.toJSON(o[i],compact));}
if(compact)
return"["+ret.join(",")+"]";else
return"["+ret.join(", ")+"]";}
if(type=="function"){throw new TypeError("Unable to convert object of type 'function' to json.");}
var ret=[];for(var k in o){var name;type=typeof(k);if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;var val=$.toJSON(o[k],compact);if(typeof(val)!="string"){continue;}
if(compact)
ret.push(name+":"+val);else
ret.push(name+": "+val);}
return"{"+ret.join(", ")+"}";};$.compactJSON=function(o)
{return $.toJSON(o,true);};$.evalJSON=function(src)
{return eval("("+src+")");};$.secureEvalJSON=function(src)
{var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};})(jQuery);
//}}}
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|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;
}
}
//}}}
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
|''ViewTemplate''|##ViewBizRegTemplate|
|''EditTemplate''|##EditBizRegTemplate|
|''StyleSheet''|##StyleSheet|
!ViewTemplate
[[ViewBizRegTemplate]]
!EditTemplate
[[EditBizRegTemplate]]
!StyleSheet
.nl {
display: block;
}
|~ViewToolbar|revisions closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|
|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|
|~RegisterToolbar|saveTiddler deleteTiddler|
//{{{
(function() {
var adaptor = config.adaptors.tiddlyweb;
var _putTiddlerCallback = adaptor.putTiddlerCallback;
adaptor.putTiddlerCallback = function(status, context, responseText, uri, xhr) {
// disable getTiddler
var _getTiddler = context.adaptor.getTiddler;
context.adaptor.getTiddler = function() {};
// call original
_putTiddlerCallback.apply(this, arguments);
// restore getTiddler
context.adaptor.getTiddler = _getTiddler;
store.setDirty(false);
};
})();
//}}}
<!--{{{-->
<!--<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>-->
<div class='title' macro='view title'></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer'>
<h2>Who you are...</h2>
<span class='nl' macro='view email wikified'>Email Address: </span>
<span class='nl' macro='view telephone wikified'>Telephone: </span>
<span class='nl' macro='view dob wikified'>D.O.B: </span>
<span class='nl' macro='view school wikified'>School/Organisation: </span>
<h2>About you...</h2>
<span class='nl' macro='view text wikified'>Experience: </span>
<span class='nl' macro='view reason_why wikified'>Reason: </span>
<span class='nl' macro='view first_time wikified'>Have you been before: </span>
</div>
<div class='title' macro='tiddler RegistrationComplete'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
|''Name:''|BackstageTiddlersPlugin|
|''Description:''|Adds a backstage panel allowing easy access to all tiddlers|
|''Author:''|JeremyRuston|
|''Source:''|http://www.osmosoft.com/#BackstageTiddlersPlugin |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/JeremyRuston/plugins/BackstageTiddlersPlugin.js |
|''Version:''|0.0.1|
|''Date:''|Feb 28, 2008|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''~CoreVersion:''|2.3|
***/
//{{{
if(!version.extensions.BackstageTiddlersPlugin) {
version.extensions.BackstageTiddlersPlugin = {installed:true};
config.tasks.tiddlers = {
text: "tiddlers",
tooltip: "Access the raw tiddlers",
content: "<<tabs txtMainTab 'Timeline' 'Timeline' TabTimeline 'All' 'All tiddlers' TabAll 'Tags' 'All tags' TabTags 'More' 'More lists' TabMore>>"};
config.backstageTasks.push("tiddlers");
} //# end of 'install only once'
//}}}
//{{{
/*
|''Name:''| CoreEnhancements|
|''Description:''|
Powers up the TiddlyWiki core to make it more TiddlyWeb friendly. See below for list of new programming bits and bobs
|
|''Version:''|0.6|
|''Date:''|APRIL 2010|
|''Source:''||
|''Author:''|Jon Robson|
|''License:''|[[BSD open source license]]|
|''CoreVersion:''|2.3|
|''Dependencies:''||
Additions:
1) toJSON (new)
allows easy conversion from string to a json which can then be passed as a jquery options parameter.
2) filterTiddlers (enhancement) - packaged as plugin
Enhanced to allow you to use fields eg. [field[val]] gives you all tiddlers with field having the value val.
[server.bag[foo]] gives you all tiddlers in bag foo
3) sortTiddlers (enhancement) - packaged as plugin
enhanced to allow sorting by a type.currently float and int are supported as well as default string.
the filter [sort(int)[field]] now sorts tiddlers by "field" where the values of field are treated as integers.
4) macro tiddler (enhancement) - packaged as plugin
* New tiddler macro accepts a template
<<tiddler bar template:foo>>
will print the tiddler foo but with the data of tiddler bar.
so if tiddler foo has text "hello <<view title>>" the result of this is "hello bar"
Code slightly changed to run anyway if tiddler text is empty and template being used.
5) macro tiddlers (new) - packaged as plugin
* allows loops - takes filter parameter and calls tiddler macro on each of the resulting tiddlers
<<tiddlers filter:[server.bag[jon]] template:Foo>> runs <<tiddler template:foo>> on each tiddler in the bag jon.
6) view macro views (enhancement)
* added generic el which allows you to specify the attribute destination of your value and the type of element to create
eg. <<view title el type:a attr:href text:hello>> for tiddler with title Bar will create <a href='bar'>hello</a>
also supports prefix and suffix parameters to append to value of tiddler attribute
eg. <<view title el type:a attr:href text:hello prefix:/foo/ suffix:.wiki>> for tiddler with title Bar will create <a href='/foo/bar.wiki'>hello</a>
Another example
<<view title el type:input attr:value attributes:{{[['type','hidden']]}}>> for tiddler called foo
creates <input type='hidden' value='foo'/>
If you do not specify a type it will use the existing element. eg. <form macro='view title el attr:action'></form> will add an attribute action to your form using the tiddler title.
7) New shadow tiddler Config (- raised ticket)
This would be an option set of tiddler slices that allow you to override default config.options and config.messages
good for enforcing different language versions / overriding mention of word tiddler
8) new config options
options.onClickTiddlerLinkCloseAllTiddlers (for onClickTiddlerLink)
options.onDisplayTiddlersCloseAllTiddlers (for displayTiddlers)
config.options.allTagsNoOpenTagButton (for onClickTag)
9) onClickTag
adjusted so it doesnt show tiddlers tagged excludeLists in the list.
10) onClickTagOpenAll
adjusted so that you open all tagged with "foo" if a tiddler is tagged "foo" and "excludeList" it is not opened.
11) new macro url
This would help establish a standardised way of accessing urls on the server and client
Proposed usage
if you accessed a url http://blah.com/wiki/recipes/foo/tiddlers.wiki
<<url>> would print /wiki/recipes/foo/tiddlers.wiki
Takes an optional parameter to get the segment
eg. <<url 2>> would print foo
<<url 3>> would print tiddlers.wiki
12) request to modify getTags function
currently if you call getTags("excludeTags") it returns a list of tags where each of those tags are not themselves tagged with excludeTags
ie. if the tags in a tiddlywiki were ['a','b','c','d','e']
you would need to create a tiddler called 'a' and tag it with 'excludeTags'
to get the list ['b','c','d','e']
This is very tedious and could be better improved if you could create a tiddler called excludeTags and tag it with all tags to exclude
eg. create a tiddler with title excludeTags and tag with 'a' 'c' and 'e' to generate a list
['b','d'] from the same list above.
13) message
extended to use views
eg.
<<message options.txtUserName view link>>
14) count macro
returns number of tiddlers matching a given filter
15) view handler extended to provide ifEmpty parameter.
<<view myfield ifEmpty:EmptyTemplate>>
When no value for myfield instead displays EmptyTemplate.
Also ifEmptyString
<<view num_comments ifEmptyString:0>>
could be used to print 'You have 0 comments.' when num_comments field empty
16) saveTiddlerWithoutOverwriting
prevents creation of new tiddlers with the default title and with an existing title
17) displayMessage
don't make it a target ='_blank'! use config.options.chkOpenInNewWindow
18) addCustomFields (ticketed)
allow user to override core settings
19) tiddler transclusion in a template
eg. [[:title]] in a ViewTemplate places the title
attempting by hacking getRecursiveTiddlerText
*/
String.prototype.toJSON = function(){var namedprms = this.parseParams(null, null, true);var options ={};for(var i=0; i < namedprms.length;i++){var nameval = namedprms[i];if(nameval.name)options[nameval.name] = nameval.value;}return options;};
//This is a hack to stop the "The tiddler '%0' doesn't yet exist. Double-click to create it" text appearing in the registration form
config.views.wikified.defaultText = "";
// This is a hack to show submit on the save button instead of "done"
config.commands.saveTiddler.text = "submit";
config.macros.tiddlersLink = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var filter = params[1];
var action = function(e){
story.displayTiddlers(e,store.filterTiddlers(filter));
}
createTiddlyButton(place,params[0],params[0],action,"tiddlersLink");
}
}
story.addConfigOptionDisplayTiddlers = story.displayTiddlers;
story.displayTiddlers = function(srcElement,titles,template,animate,unused,customFields,toggle)
{
if(config.options.onDisplayTiddlersCloseAllTiddlers){
this.closeAllTiddlers();
}
this.addConfigOptionDisplayTiddlers(srcElement,titles,template,animate,unused,customFields,toggle);
};
config.macros.message.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
if(params[0]) {
var names = params[0].split(".");
var lookupMessage = function(root,nameIndex) {
if(names[nameIndex] in root) {
if(nameIndex < names.length-1)
return (lookupMessage(root[names[nameIndex]],nameIndex+1));
else
return root[names[nameIndex]];
} else
return null;
};
var m = lookupMessage(config,0);
if(m == null)
m = lookupMessage(window,0);
if(m == null) m = "";
var oldParams = params;
var formatMsg = function(m){m.toString().format(params.splice(1));};
if(oldParams[1]){
var type = oldParams[1];
var newParams = oldParams.splice(1);
var value = m;
var handler = config.macros.view.views[type];
var newParamString = paramString;
if(handler)
handler(value,place,newParams,wikifier,newParamString,tiddler);
else
jQuery(place).append(value);
}
else {
createTiddlyText(place,m);
}
}
};
/*
config.macros.viewConfig = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
if(!params || params.length <2) return;
if(config[params[0]]){
var value = config[params[0]][params[1]];
var type = params[2];
var handler = config.macros.view.views[type];
if(handler)
handler(value,place,params,wikifier,paramString,tiddler);
else
jQuery(place).append(value);
}
}
}
*/
config.macros.count = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var count =0;
var namedprms = paramString.parseParams(null, null, true);
var options ={};
for(var i=0; i < namedprms.length;i++){
var nameval = namedprms[i];
options[nameval.name] = nameval.value;
}
var tiddlers = store.filterTiddlers(options.filter);
//console.log(tiddlers);
jQuery(place).append(tiddlers.length);
}
};
config.macros.url = {
handler: function(place,macroName,params){
var url = window.location.pathname;
if(params && params[0]){
url =url.substr(1); //remove initial '/'
var print = url.split("/")[parseInt(params[0])];
}
else{
print =url;
}
jQuery(place).append(decodeURI(print));
}
}
function loadConfig(){
var configShadow= store.calcAllSlices("Config");
if(configShadow){
for(var c in configShadow){
//console.log("loading " +c);
var ids = c.split(".");
if(ids && ids.length > 1){
var id1 = ids[0];
var id2 = ids[1];
//console.log(id1,id2);
var location = config;
for(var i=0; i < ids.length-1; i++){
var ref = ids[i];
if(location && location[ref])location = location[ref];
else{
location = false;
}
}
if(location){
var value =configShadow[c].replace(/\\n/gi,"\n");
if(value == 'false' || value== 'true' ||value.indexOf("{{")==0){
value = value.replace("{{","").replace("}}","")
try{
value = eval(value);
}
catch(e){};
}
location[ids[ids.length-1]] = value;
}
}
}
}
refreshDisplay();
}
function onClickTiddlerLink(ev)
{
var e = ev || window.event;
var target = resolveTarget(e);
var link = target;
var title = null;
var fields = null;
var noToggle = null;
do {
title = link.getAttribute("tiddlyLink");
fields = link.getAttribute("tiddlyFields");
noToggle = link.getAttribute("noToggle");
link = link.parentNode;
} while(title == null && link != null);
if(!store.isShadowTiddler(title)) {
var f = fields ? fields.decodeHashMap() : {};
fields = String.encodeHashMap(merge(f,config.defaultCustomFields,true));
}
if(title) {
var toggling = e.metaKey || e.ctrlKey;
if(config.options.chkToggleLinks)
toggling = !toggling;
if(noToggle)
toggling = false;
if(store.getTiddler(title))
fields = null;
if(config.options.onClickTiddlerLinkCloseAllTiddlers) story.closeAllTiddlers();
story.displayTiddler(target,title,null,true,null,fields,toggling);
}
clearMessage();
return false;
}
story.addTiddler = function(){}
//"server.page.revision"
config.commands.saveTiddlerWithoutOverwriting={
text: "done",
tooltip: "Save changes to this tiddler",
tiddlerExistsMsg:"This tiddler already exists!",
usingDefaultNameMsg: "Please give your idea a more useful name!",
handler: function(event,src,title){
var command = this;
var tiddlerElem = story.getTiddler(title);
var fields = {};
story.gatherSaveFields(tiddlerElem,fields);
var saveTitle = fields.title;
if(config.macros.newTiddler.title == saveTitle){
alert(this.usingDefaultNameMsg);
return;
}
var tiddler = store.getTiddler(saveTitle);
if(!tiddler){ //tiddler is a new one
window.confirmExit = false;
window.checkUnsavedChanges = false;
var ws = fields["server.workspace"];
var url = fields["server.host"]+"/" + ws +"/tiddlers/"+saveTitle+".txt";
ajaxReq({url:url,
success:function(r){
window.confirmExit = true;
window.checkUnsavedChanges = true;
},
error: function(){
window.confirmExit = false;
window.checkUnsavedChanges = false;
var newTitle = story.saveTiddler(title,false);
if(newTitle)
story.displayTiddler(null,newTitle);
return false;
}
});
}
else{
alert(command.tiddlerExistsMsg);
}
}
}
/* tiddler transclusion */
Story.prototype.getTemplateForTiddler = function(title,template,tiddler)
{
var matcher = function(match,field){
if(tiddler[field]) return tiddler[field];
else if(tiddler.fields[field]) return tiddler.fields[field];
else return "";
}
var text= store.getRecursiveTiddlerText(template,null,10);
return text.replace(/\[\[:([^\]]*)\]\]/gi,matcher);;
};
Story.prototype.addCustomFields = function(place,customFields)
{
var fields = customFields.decodeHashMap();
var html = '<div class="customFields" style="display:none;">';
for(var t in fields) {
html += '<input type="text" value="'+fields[t]+'" edit="'+t+'"/>';
}
jQuery(place).prepend(html);
};
TiddlyWiki.prototype.getTags = function(excludeTag)
{
var results = [];
var excludeList =[];
if(excludeTag){
var tiddler = store.getTiddler(excludeTag);
if(tiddler)excludeList = tiddler.tags;
}
this.forEachTiddler(function(title,tiddler) {
var n = true;
for(var g=0; g<tiddler.tags.length; g++) {
var tag = tiddler.tags[g];
if(excludeList.indexOf(tag) > -1) n = false;
for(var c=0; c<results.length; c++) {
if(results[c][0] == tag) {
n = false;
results[c][1]++;
}
}
if(n && excludeList) {
var t = this.fetchTiddler(tag);
if(t && t.isTagged(excludeTag))
n = false;
}
if(excludeList.indexOf(tag) !=-1) n =false;
if(n)
results.push([tag,1]);
}
});
results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
return results;
};
onClickTagOpenAll=function(ev)
{
var tiddlers = store.getTaggedTiddlers(this.getAttribute("tag"));
var tiddlersToOpen = [];
for(var i=0; i < tiddlers.length;i++){
var tid = tiddlers[i];
if(tid.tags.indexOf("excludeLists") == -1) tiddlersToOpen.push(tid);
}
story.displayTiddlers(this,tiddlersToOpen);
return false;
}
onClickTag = function(ev)
{
var e = ev || window.event;
var popup = Popup.create(this);
addClass(popup,"taggedTiddlerList");
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
if(popup && tag) {
var tagged = store.getTaggedTiddlers(tag);
var titles = [];
var li,r;
for(r=0;r<tagged.length;r++) {
if(tagged[r].title != title)
titles.push(tagged[r].title);
}
var lingo = config.views.wikified.tag;
if(titles.length > 0) {
var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
openAll.setAttribute("tag",tag);
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
for(r=0; r<titles.length; r++) {
var taggedTiddler = titles[r]
var taggedTid = store.getTiddler(taggedTiddler);
if(taggedTid.tags.indexOf("excludeLists") == -1)createTiddlyLink(createTiddlyElement(popup,"li"),taggedTiddler,true);
}
} else {
createTiddlyElement(popup,"li",null,"disabled",lingo.popupNone.format([tag]));
}
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
if(!config.options.allTagsNoOpenTagButton){
var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
createTiddlyText(h,lingo.openTag.format([tag]));
}
}
Popup.show();
e.cancelBubble = true;
if(e.stopPropagation) e.stopPropagation();
return false;
}
displayMessage = function(text,linkText)
{
var e = getMessageDiv();
if(!e) {
alert(text);
return;
}
if(linkText) {
var link = createTiddlyElement(e,"a",null,null,text);
link.href = linkText;
if(config.options.chkOpenInNewWindow)link.target = "_blank";
} else {
e.appendChild(document.createTextNode(text));
}
}
loadConfig();
//}}}
|''ViewTemplate''|##ViewRegTemplate|
|''EditTemplate''|##EditRegTemplate|
|''StyleSheet''|##StyleSheet|
!ViewTemplate
[[ViewRegTemplate]]
!EditTemplate
[[EditRegTemplate]]
!StyleSheet
.nl {
display: block;
}
/***
|''Name''|ServerSideSavingPlugin|
|''Description''|server-side saving|
|''Author''|FND|
|''Version''|0.5.3|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/ServerSideSavingPlugin.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5.3|
|''Keywords''|serverSide|
!Notes
This plugin relies on a dedicated adaptor to be present.
The specific nature of this plugin depends on the respective server.
!Revision History
!!v0.1 (2008-11-24)
* initial release
!!v0.2 (2008-12-01)
* added support for local saving
!!v0.3 (2008-12-03)
* added Save to Web macro for manual synchronization
!!v0.4 (2009-01-15)
* removed ServerConfig dependency by detecting server type from the respective tiddlers
!!v0.5 (2009-08-25)
* raised CoreVersion to 2.5.3 to take advantage of core fixes
!To Do
* conflict detection/resolution
* rename to ServerLinkPlugin?
* document deletion/renaming convention
!Code
***/
//{{{
readOnly = false; //# enable editing over HTTP
(function($) {
var plugin;
plugin = config.extensions.ServerSideSavingPlugin = {};
plugin.locale = {
saved: "%0 saved successfully",
saveError: "Error saving %0: %1",
saveConflict: "Error saving %0: edit conflict",
deleted: "Removed %0",
deleteError: "Error removing %0: %1",
deleteLocalError: "Error removing %0 locally",
removedNotice: "This tiddler has been deleted.",
connectionError: "connection could not be established"
};
plugin.sync = function() {
store.forEachTiddler(function(title, tiddler) {
if(tiddler.fields.deleted === "true") {
plugin.removeTiddler(tiddler);
} else if(tiddler.isTouched() && !tiddler.doNotSave() &&
tiddler.getServerType() && tiddler.fields["server.host"]) {
plugin.saveTiddler(tiddler);
}
});
};
plugin.saveTiddler = function(tiddler) {
try {
var adaptor = this.getTiddlerServerAdaptor(tiddler);
} catch(ex) {
return false;
}
var context = {
tiddler: tiddler,
changecount: tiddler.fields.changecount
};
context.workspace = tiddler.fields["server.workspace"];
var req = adaptor.putTiddler(tiddler, context, {}, this.saveTiddlerCallback);
return req ? tiddler : false;
};
plugin.saveTiddlerCallback = function(context, userParams) {
var tiddler = context.tiddler;
if(context.status) {
if(tiddler.fields.changecount == context.changecount) { //# check for changes since save was triggered
tiddler.clearChangeCount();
} else if(tiddler.fields.changecount > 0) {
tiddler.fields.changecount -= context.changecount;
}
plugin.reportSuccess("saved", tiddler);
store.setDirty(false);
} else {
if(context.httpStatus == 412) {
plugin.reportFailure("saveConflict", tiddler);
} else {
plugin.reportFailure("saveError", tiddler, context);
}
}
};
plugin.removeTiddler = function(tiddler) {
try {
var adaptor = this.getTiddlerServerAdaptor(tiddler);
} catch(ex) {
return false;
}
context = { tiddler: tiddler };
context.workspace = tiddler.fields["server.workspace"];
var req = adaptor.deleteTiddler(tiddler, context, {}, this.removeTiddlerCallback);
return req ? tiddler : false;
};
plugin.removeTiddlerCallback = function(context, userParams) {
var tiddler = context.tiddler;
if(context.status) {
if(tiddler.fields.deleted === "true") {
store.deleteTiddler(tiddler.title);
} else {
plugin.reportFailure("deleteLocalError", tiddler);
}
plugin.reportSuccess("deleted", tiddler);
store.setDirty(false);
} else {
plugin.reportFailure("deleteError", tiddler, context);
}
};
plugin.getTiddlerServerAdaptor = function(tiddler) { // XXX: rename?
var type = tiddler.fields["server.type"] || config.defaultCustomFields["server.type"];
return new config.adaptors[type]();
};
plugin.reportSuccess = function(msg, tiddler) {
displayMessage(plugin.locale[msg].format([tiddler.title]));
};
plugin.reportFailure = function(msg, tiddler, context) {
context = context || {};
var desc = context.httpStatus ? context.statusText : plugin.locale.connectionError;
displayMessage(plugin.locale[msg].format([tiddler.title, desc]));
};
config.macros.saveToWeb = { // XXX: hijack existing sync macro?
locale: { // TODO: merge with plugin.locale?
btnLabel: "save to web",
btnTooltip: "synchronize changes",
btnAccessKey: null
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
createTiddlyButton(place, this.locale.btnLabel, this.locale.btnTooltip,
plugin.sync, null, null, this.locale.btnAccessKey);
}
};
// hijack saveChanges to trigger remote saving
var _saveChanges = saveChanges;
saveChanges = function(onlyIfDirty, tiddlers) {
if(window.location.protocol == "file:") {
_saveChanges.apply(this, arguments);
} else {
plugin.sync();
}
};
// override removeTiddler to flag tiddler as deleted -- XXX: use hijack to preserve compatibility?
TiddlyWiki.prototype.removeTiddler = function(title) { // XXX: should override deleteTiddler instance method?
var tiddler = this.fetchTiddler(title);
if(tiddler) {
tiddler.tags = ["excludeLists", "excludeSearch", "excludeMissing"];
tiddler.text = plugin.locale.removedNotice;
tiddler.fields.deleted = "true"; // XXX: rename to removed/tiddlerRemoved?
tiddler.incChangeCount();
this.notify(title, true);
this.setDirty(true);
}
};
})(jQuery);
//}}}
/***
|''Name''|RevisionsCommandPlugin|
|''Description''|provides access to tiddler revisions|
|''Author''|FND|
|''Contributors''|Martin Budden|
|''Version''|0.1.8|
|''Status''|@@beta@@|
|''Source''|http://devpad.tiddlyspot.com/#RevisionsCommandPlugin|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/plugins/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.4.2|
|''Keywords''|serverSide|
!Usage
Extend [[ToolbarCommands]] with {{{revisions}}}.
!Revision History
!!v0.1 (2009-07-23)
* initial release (renamed from experimental ServerCommandsPlugin)
!To Do
* strip server.* fields from revision tiddlers
* resolve naming conflicts
* i18n, l10n
* code sanitizing
* documentation
* rename?
!Code
***/
//{{{
(function() {
if(!version.extensions.ServerCommandsPlugin) { //# ensure that the plugin is only installed once
version.extensions.ServerCommandsPlugin = { installed: true };
var cmd; //# alias
cmd = config.commands.revisions = {
type: "popup",
hideShadow: true,
text: "revisions",
tooltip: "display tiddler revisions",
revTooltip: "", // TODO: populate dynamically?
loadLabel: "loading...",
loadTooltip: "loading revision list",
selectLabel: "select",
selectTooltip: "select revision for comparison",
selectedLabel: "selected",
compareLabel: "compare",
revSuffix: " [rev. #%0]",
diffSuffix: " [diff: #%0 #%1]",
dateFormat: "YYYY-0MM-0DD 0hh:0mm",
handlePopup: function(popup, title) {
stripSuffix = function(type, title) {
var str = cmd[type + "Suffix"];
var i = str.indexOf("%0");
i = title.indexOf(str.substr(0, i));
if(i != -1) {
title = title.substr(0, i);
}
return title;
};
title = stripSuffix("rev", title);
title = stripSuffix("diff", title);
var tiddler = store.getTiddler(title);
var type = this._getField("server.type", tiddler);
var adaptor = new config.adaptors[type]();
var limit = null; // TODO: customizable
var context = {
host: this._getField("server.host", tiddler),
workspace: this._getField("server.workspace", tiddler)
};
var loading = createTiddlyButton(popup, cmd.loadLabel, cmd.loadTooltip);
var params = { popup: popup, loading: loading, origin: title };
adaptor.getTiddlerRevisionList(title, limit, context, params, this.displayRevisions);
},
displayRevisions: function(context, userParams) {
var callback = function(ev) {
var e = ev || window.event;
var revision = resolveTarget(e).getAttribute("revision");
context.adaptor.getTiddlerRevision(tiddler.title, revision, context,
userParams, cmd.displayTiddlerRevision);
};
removeNode(userParams.loading);
var table = createTiddlyElement(userParams.popup, "table");
for(var i = 0; i < context.revisions.length; i++) {
var tiddler = context.revisions[i];
var row = createTiddlyElement(table, "tr");
var timestamp = tiddler.modified.formatString(cmd.dateFormat);
var revision = tiddler.fields["server.page.revision"];
var cell = createTiddlyElement(row, "td");
createTiddlyButton(cell, timestamp, cmd.revTooltip, callback, null,
null, null, { revision: revision });
cell = createTiddlyElement(row, "td", null, null, tiddler.modifier);
cell = createTiddlyElement(row, "td");
createTiddlyButton(cell, cmd.selectLabel, cmd.selectTooltip,
cmd.revisionSelected, null, null, null,
{ index:i, revision: revision, col: 2 });
cmd.context = context; // XXX: unsafe (singleton)!?
}
},
revisionSelected: function(ev) {
var e = ev || window.event;
e.cancelBubble = true;
if(e.stopPropagation) e.stopPropagation();
var n = resolveTarget(e);
var index = n.getAttribute("index");
var col = n.getAttribute("col");
while(!index || !col) {
n = n.parentNode;
index = n.getAttribute("index");
col = n.getAttribute("col");
}
cmd.revision = n.getAttribute("revision");
var table = n.parentNode.parentNode.parentNode;
var rows = table.childNodes;
for(var i = 0; i < rows.length; i++) {
var c = rows[i].childNodes[col].firstChild;
if(i == index) {
if(c.textContent) {
c.textContent = cmd.selectedLabel;
} else {
c.text = cmd.selectedLabel;
}
} else {
if(c.textContent) {
c.textContent = cmd.compareLabel;
} else {
c.text = cmd.compareLabel;
}
c.onclick = cmd.compareSelected;
}
}
},
compareSelected: function(ev) {
var e = ev || window.event;
var n = resolveTarget(e);
var context = cmd.context;
context.rev1 = n.getAttribute("revision");
context.rev2 = cmd.revision;
context.tiddler = context.revisions[n.getAttribute("index")];
context.format = "unified";
context.adaptor.getTiddlerDiff(context.tiddler.title, context,
context.userParams, cmd.displayTiddlerDiffs);
},
displayTiddlerDiffs: function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title += cmd.diffSuffix.format([context.rev1, context.rev2]);
tiddler.text = context.diff;
tiddler.fields.doNotSave = "true"; // XXX: correct?
if(!store.getTiddler(tiddler.title)) {
store.addTiddler(tiddler);
}
var src = story.getTiddler(userParams.origin);
story.displayTiddler(src, tiddler);
},
displayTiddlerRevision: function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title += cmd.revSuffix.format([tiddler.fields["server.page.revision"]]);
tiddler.fields.doNotSave = "true"; // XXX: correct?
if(!store.getTiddler(tiddler.title)) {
store.addTiddler(tiddler);
}
var src = story.getTiddler(userParams.origin);
story.displayTiddler(src, tiddler);
},
_getField: function(name, tiddler) {
return tiddler.fields[name] || config.defaultCustomFields[name];
}
};
} //# end of "install only once"
})();
//}}}
body {
font-family: georgia, times, serif;
background: [[ColorPalette::Foreground]];
}
h1, h2, h3, h4, h5 {
font-weight: normal;
color: #B63322;
}
a {
color:#2266AA;
font-weight: normal;
font-family: georgia, times;
}
a:hover {
color:#FFFFFF;
background-color:#2266AA;
font-weight: normal;
font-family: georgia, times;
}
.externalLink {
text-decoration:none;
}
.tiddlyLinkExisting {
font-weight: normal;
font-family: georgia; times;
}
div#contentWrapper {
margin: 0px auto;
position: relative;
text-align: left;
width: 900px;
}
#sidebar {
display: none;
}
#displayArea {
background: [[ColorPalette::Background]];
margin: 0em 3em 0em 3em;
}
#tiddlerDisplay {
}
.header {
font-family: "gill sans", helvetica, sans-serif;
padding: 0.25em 0.25em 0.25em 0.25em;
}
.siteTitle {
left: -1em;
color: [[ColorPalette::Background]];
font-size: 36pt;
}
.tiddler {
font-size: 14pt;
}
.tiddler .subtitle {
display: none;
}
.title {
font-family: "gill sans", helvetica, sans-serif;
font-weight: normal;
font-size: 24pt;
}
.tagging, .tagged {
display: none;
}
.viewer textarea {
width: 100%;
}
/******************
Added by Colm
******************/
.edit-bag {
display: none;
}
.title {
color: #B63322;
}
span.simple-editor input, div.simple-editor {
width: 50%;
margin: 0 0 5px 0;
}
div.register-toolbar {
text-align: center; margin-top: 10px;
}
span.free-editor input { margin:0 0 5px 0; }
span.free-editor fieldset div textarea {
height: 100px;
margin: 0 0 5px 0;
}
#messageArea { position: absolute; top: -9999px; }
|Name|ListboxPlugin|
|Source|http://www.TiddlyTools.com/#ListboxPlugin|
|Documentation|http://www.TiddlyTools.com/#ListboxPluginInfo|
|Version|1.4.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for ListboxPlugin|
The {{{<<select>>}}} macro allows you to set tiddler field values by selecting pre-configured enumerated values from a listbox/droplist control.
!!!!!Usage
<<<
in tiddler content:
{{{
<<select fieldname@tiddlername value value value ...
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername label=value label=value label=value ...
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername =tagvalue allowEdit
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername "=tag expression" allowEdit
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername +TiddlerName allowEdit
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
<<select fieldname@tiddlername *TiddlerName allowEdit
rows:nn width:xxx "prompt:..." autoSave allowBlank allowOther allowMultiple>>
}}}
in a custom [[EditTemplate]] or [[ViewTemplate]]:
{{{
<div class="editor" macro="select ..."></div>
}}}
//where://
*''fieldname@tiddlername'' (or ''=cookiename''){{block{
<<<
Specifies the tiddler field associated with the list display. The "@tiddlername" portion is optional and, when omitted (or the special keyword, "@here" is used), the current tiddler is assumed. Alternatively, if the fieldname begins with an equal sign (=), then it will be used as a TiddlyWiki option cookie reference and the selected value will be ''assigned to that cookiename //instead// of being stored in a tiddler field''. Note: when a cookie reference is used, any "@tiddlername" portion that may be present in the syntax will be //ignored//.
<<<
}}}
*{{block{
''value value value ...'' //or// ''label=value label=value label=value ...'' //(inline list definition)//
''+~TiddlerName'' //or// ''*~TiddlerName'' //(tiddler-based list definition)//
''=tagvalue'' //or// ''"=tag expression"'' //(tag-based list definition)//
<<<
Specifies list items as simple values or label/value pairs.
You can use the ''+~TiddlerName'' or ''*~TiddlerName'' syntax to define the values or label/value pairs using a tiddler containing an "HR-separated" list, where each list item is one or two lines of text, separated from the next item by a horizontal rule: """----""". The first line of each item contains the value or label=value that will appear in the list. The second, optional line allows you to specify custom tooltip help text for that list item.
The default tooltip for a list item is: "{{{set fieldname@tiddlername=itemvalue}}}". Note: if all list entries are single-line (i.e., you are not defining ANY custom tooltips), you can omit the horizontal rule between entries... each line of text will be treated as a separate list entry.
If you use "*" preceding the ~TiddlerName, the contents of the tiddler will first be processed by the TiddlyWiki parser and that output will then be used as the list definition. This allows you to apply macros and scripts to //dynamically generate list definitions// based on the current document contents (such as available tag names).
You can also use the ''=tagvalue'' syntax to generate a list whose items are the names of tiddlers tagged with that value (e.g., "=systemConfig" to list all plugins, or "=friends" to list all tiddlers tagged as "friends"). If you have MatchTagsPlugin installed, you can use Boolean tag //expressions// (e.g., "=friends or (lovers and not crazy)", to list only tiddlers that have a suitable combination of tags.
<<<
}}}
*''allowEdit'' //(for use with +~TiddlerName or *~TiddlerName param only)//{{block{
<<<
adds optional "edit list..." item to the end of the list, to enable quick editing of a tiddler-based list definition. Note: if the ''+~TiddlerName'' parameter refers to a tiddler that does not yet exist, the "edit list..." item is automatically added to the list, even if ''allowEdit'' was not specified. This allows you to place an 'empty' tiddler-based list into your content (e.g., """<<select fieldname =NewTiddlerName>>"""), and then create and define the tiddler-based list later on.
<<<
}}}
*''rows:nn''{{block{
<<<
specifies the number of lines to display in the list. If rows=1, a 'droplist' is displayed. If rows>1 a fixed-height listbox is used. By default (or if rows=0 is used), the listbox is displayed with enough lines to show all items without scrolling (i.e., "fit to contents - vertically")
<<<
}}}
*''width:xxx''{{block{
<<<
specifies the width of the list, using a CSS dimension value (px, em, in, cm, or %). The default is auto (i.e., "fit to contents - horizontally").
<<<
}}}
*''"prompt:..."''{{block{
<<<
specifies 'guide text' to display as the first item in the list. Selecting this item does not change the value stored in the field.
<<<
}}}
*''autoSave''{{block{
<<<
when used in EditTemplate, this keyword forces selection changes to be applied immediately rather than waiting for the "done" command to be invoked. Note: because the standard ViewTemplate toolbar does not have a "done" command to signal the end of the editing activity, ''autoSave'' is always enabled when working with a selection list that is being displayed in 'view mode'.
<<<
}}}
*''allowBlank''{{block{
<<<
when the value of a tiddler field is "undefined", a 'blank' item is added at the beginning of the list to represent the undefined field value. When a field value is subsequently selected, the blank item is removed from the list. Use the ''allowBlank'' keyword to always include the blank item in the list. Selecting the blank item sets the field value back to "undefined" (i.e., deletes the field).
<<<
}}}
*''allowOther''{{block{
<<<
when the value of a tiddler field does not match any of the values in the list, a special 'other' item is added at the end of the list so that the unrecognized field value can be shown. If another field value is subsequently selected, the 'other' item is removed from the list. Use the ''allowOther'' keyword to always include the 'other item in the list. When this item is selected, you will be prompted to enter a custom value to assign to the field.
<<<
}}}
*''allowMultiple''{{block{
<<<
when used with a listbox (e.g, rows>1), permits selection of multiple items using ctrl-click and shift-click. Selected values are stored in the tiddler field as a space-separated list, with brackets ({{{[[...]]}}}}) used as needed around values containing spaces. //note: multiple selection is not supported by droplists (rows=1)//
<<<
}}}
<<<
!!!!!Examples
<<<
''inline list definition:''
{{{<<select thing rows:1 eenie meenie miney moe>>}}}
<<select thing rows:1 eenie meenie miney moe>>
{{{<<select size rows:1 "prompt:select a show size..." xsmall=30 small=32 medium=34 large=36 xlarge=38>>}}}
<<select size rows:1 "prompt:select a show size..." xsmall=30 small=32 medium=34 large=36 xlarge=38>>
{{{<<select size allowOther "prompt:select a shoe size..." xsmall=30 small=32 medium=34 large=36 xlarge=38>>}}}
<<select size allowOther "prompt:select a shoe size..." xsmall=30 small=32 medium=34 large=36 xlarge=38>>
{{{<<select gender Male Female>>}}}
<<select gender Male Female>>
''tiddler-based list definition:''
{{{<<select color rows:1 +ListboxSample>>}}}
<<select color rows:1 +ListboxSample>>
{{{<<select color allowBlank allowOther allowMultiple +ListboxSample allowEdit>>}}}
<<select color allowBlank allowOther allowMultiple +ListboxSample allowEdit>>
{{{<<select demo@ListboxDemoTarget +ListboxNewSample>>}}}
<<select demo@ListboxDemoTarget +ListboxNewSample>>
''tag-based list definition:''
{{{<<select plugins rows:1 =systemConfig>>}}}
<<select plugins rows:1 allowBlank =systemConfig>>
{{{<<select samples rows:1 allowBlank =sample>>}}}
<<select samples rows:1 =sample>>
<<<
!!!!!Revisions
<<<
2010.03.14 1.4.1 use filterTiddlers() instead of getTaggedTiddlers() - use MatchTagsPlugin for tag expressions
2009.09.02 1.4.0 added 'prompt:...' param
2009.09.02 1.3.0 added special handling for tags field
2009.06.15 1.2.3 in setFieldValue(), eliminate extra brackets around single value selections
2009.06.15 1.2.2 fixed infinite loop problem in refresh()
2009.06.15 1.2.1 if not allowMultiple, handle field values containing space-separated lists as single values
2009.05.31 1.2.0 added allowMultiple flag. Rewrote handler to allow option params in any order. Corrected handling of blank/other values.
2008.07.22 1.1.0 added "=cookiename" syntax for storing selected value in cookie instead of a tiddler field
2008.04.28 1.0.1 added "=tagvalue" syntax for generating lists of tiddlers tagged with a given value
2007.08.31 0.8.2 corrected handling for "@tiddlername" syntax for non-default 'target' tiddler.
2007.08.06 0.8.1 added support for "@here" keyword syntax and cleaned up handling for identifying 'target' tiddler. Also added 'onclick' handler for "other:" item, so that prompt dialog is presented even if "other" was already selected (and hence, no "onchange" event)
2007.07.29 0.8.0 added getWikifiedData() and use of "*" prefix on TiddlerName so macros or inline scripts embedded in listbox definitions can generate dynamic lists based on current document content.
2007.07.26 0.7.3 fixed call to config.macros.select.setFieldValue()
2007.07.24 0.7.2 in setFieldValue(), 'touch' target tiddler AFTER setting value to avoid early refresh event that steps on listbox attributes, causing a fatal error (in IE only).
2007.06.28 0.7.1 in render(), retrieve current val from tiddler editor control (when editing) or use stored field (when viewing).
2007.05.29 0.7.0 split render() logic from handler(), added refresh() notification to auto sync lists that use +TiddlerName definition
2007.05.15 0.6.1 code/documentation cleanup
2007.05.14 0.6.0 lots more options
2007.05.12 0.5.0 started
<<<
!Who are you?
First name
<<edit firstname>>
Surname
<<edit surname>>
e-mail
<<edit email>>
Telephone number
<<edit telephone>>
Date of birth
<<edit dob>>
School / Organisation
<<edit school>>
Which location is best for you
<<select alpha rows:1 London Manchester Brighton>>
!A bit about you...
Tell us about your level of experience, if you could point to anything you've built that'd be great!
<<edit experience 5>>
Why would you like to get involved in Young Rewired State
<<edit why 5>>
Have you participated in a Young Rewired State event before?
<<select alpha rows:1 Yes No>>
//Powered by [[TiddlyWiki|http://tiddlywiki.com]] and [[TiddlyWeb|http://tiddlyweb.com]]
//{{{
//This is a hack to stop the "The tiddler '%0' doesn't yet exist. Double-click to create it" text appearing in the registration form
config.views.wikified.defaultText = "";
// This is a hack to show submit on the save button instead of "done"
config.commands.saveTiddler.text = "submit";
config.extensions.ServerSideSavingPlugin.saveTiddlerCallback_orig
= config.extensions.ServerSideSavingPlugin.saveTiddlerCallback;
config.extensions.ServerSideSavingPlugin.saveTiddlerCallback =
function(context,
userParams) {
config.extensions.ServerSideSavingPlugin.saveTiddlerCallback_orig(context,
userParams);
store.setDirty(false);
}
//}}}