Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
/***
|Name|AliasPlugin|
|Source|http://www.TiddlyTools.com/#AliasPlugin|
|Documentation|http://www.TiddlyTools.com/#AliasPluginInfo|
|Version|1.1.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Create text-substitution macros|
Define macros for abbreviations and other "aliases", and then embed them in the rest of your tiddler content to quickly insert common terms, phrases and links without a lot of repetitive typing.
!!!!!Documentation
> see [[AliasPluginInfo]]
!!!!!Revisions
<<<
2009.09.09 [1.1.1] 'tiddler' arg passed to wikify() so aliases containing macros render with correct context
| Please see [[AliasPluginInfo]] for previous revision details |
2005.08.12 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.AliasPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2009,9,9)};
config.macros.alias= { };
config.macros.alias.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var alias=params.shift(); if (!alias) return; alias=alias.replace(/ /g,"_"); // don't allow spaces in alias
if (config.macros[alias]==undefined) { // create new macro (as needed)
config.macros[alias] = { };
config.macros[alias].handler =
function (place,macroName,params,wikifier,paramString,tiddler)
{ wikify(config.macros[macroName].text.format(params),place,null,tiddler); }
}
config.macros[alias].text = params[0]?params.join(' '):alias; // set alias text
}
//}}}
/***
|''Name:''|AnnotationsPlugin|
|''Description:''|Inline annotations for tiddler text.|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#AnnotationsPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.0|
|''Date:''||
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Usage:
*{{{((text to annotate(annotation goes here)))}}}
* To include the text being annotated, in the popup as a title, put {{{^}}} as the first letter of the annotation text.
** {{{((text to annotate(^annotation goes here)))}}}
!!Examples:
Mouse over, the text below:
* ((banana(the best fruit in the world)))
* ((banana(^ the best fruit in the world)))
***/
// /%
config.formatters.unshift({name:"annotations",match:"\\(\\(",lookaheadRegExp:/\(\((.*?)\((\^?)((?:.|\n)*?)\)\)\)/g,handler:function(w){
this.lookaheadRegExp.lastIndex=w.matchStart;
var _2=this.lookaheadRegExp.exec(w.source);
if(_2&&_2.index==w.matchStart){
var _3=createTiddlyElement(w.output,"span",null,"annosub",_2[1]);
_3.anno=_2[3];
if(_2[2]){
_3.subject=_2[1];
}
_3.onmouseover=this.onmouseover;
_3.onmouseout=this.onmouseout;
_3.ondblclick=this.onmouseout;
w.nextMatch=_2.index+_2[0].length;
}
},onmouseover:function(e){
popup=createTiddlyElement(document.body,"div",null,"anno");
this.popup=popup;
if(this.subject){
wikify("!"+this.subject+"\n",popup);
}
wikify(this.anno,popup);
addClass(this,"annosubover");
Popup.place(this,popup,{x:25,y:7});
},onmouseout:function(e){
removeNode(this.popup);
this.popup=null;
removeClass(this,"annosubover");
}});
setStylesheet(".anno{position:absolute;border:2px solid #000;background-color:#DFDFFF; color:#000;padding:0.5em;max-width:15em;width:expression(document.body.clientWidth > (255/12) *parseInt(document.body.currentStyle.fontSize)?'15em':'auto' );}\n"+".anno h1, .anno h2{margin-top:0;color:#000;}\n"+".annosub{background:#ccc;}\n"+".annosubover{z-index:25; background-color:#DFDFFF;cursor:help;}\n","AnnotationStyles");
// %/
/***
|Name|AttachFilePluginFormatters|
|Source|http://www.TiddlyTools.com/#AttachFilePluginFormatters|
|Version|4.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1.3|
|Type|plugin|
|Description|run-time library for displaying attachment tiddlers|
Runtime processing for //rendering// attachment tiddlers created by [[AttachFilePlugin]]. Attachment tiddlers are tagged with<<tag attachment>>and contain binary file content (e.g., jpg, gif, pdf, mp3, etc.) that has been stored directly as base64 text-encoded data or can be loaded from external files stored on a local filesystem or remote web server. Note: after creating new attachment tiddlers, you can remove [[AttachFilePlugin]], as long as you retain //this// tiddler (so that images can be rendered later on).
!!!!!Formatters
<<<
This plugin extends the behavior of the following TiddlyWiki core "wikify()" formatters:
* embedded images: {{{[img[tooltip|image]]}}}
* linked embedded images: {{{[img[tooltip|image][link]]}}}
* external/"pretty" links: {{{[[label|link]]}}}
''Please refer to AttachFilePlugin (source: http://www.TiddlyTools.com/#AttachFilePlugin) for additional information.''
<<<
!!!!!Revisions
<<<
2009.10.10 [4.0.1] in fileExists(), check for IE to avoid hanging Chrome during startup
2009.06.04 [4.0.0] changed attachment storage format to use //sections// instead of embedded substring markers.
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.10.29 [3.7.0] more code reduction: removed upload handling from AttachFilePlugin (saves ~7K!)
2007.10.28 [3.6.0] removed duplicate formatter code from AttachFilePlugin (saves ~10K!) and updated documentation accordingly. This plugin ([[AttachFilePluginFormatters]]) is now //''required''// in order to display attached images/binary files within tiddler content.
2006.05.20 [3.4.0] through 2007.03.01 [3.5.3] sync with AttachFilePlugin
2006.05.13 [3.2.0] created from AttachFilePlugin v3.2.0
<<<
!!!!!Code
***/
// // version
//{{{
version.extensions.AttachFilePluginFormatters= {major: 4, minor: 0, revision: 1, date: new Date(2009,10,10)};
//}}}
//{{{
if (config.macros.attach==undefined) config.macros.attach= { };
//}}}
//{{{
if (config.macros.attach.isAttachment==undefined) config.macros.attach.isAttachment=function (title) {
var tiddler = store.getTiddler(title);
if (tiddler==undefined || tiddler.tags==undefined) return false;
return (tiddler.tags.indexOf("attachment")!=-1);
}
//}}}
//{{{
// test for local file existence - returns true/false without visible error display
if (config.macros.attach.fileExists==undefined) config.macros.attach.fileExists=function(f) {
if(window.Components) { // MOZ
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
catch(e) { return false; } // security access denied
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
try { file.initWithPath(f); }
catch(e) { return false; } // invalid directory
return file.exists();
}
else if (config.browser.isIE) { // IE
var fso = new ActiveXObject("Scripting.FileSystemObject");
return fso.FileExists(f);
}
else return true; // other browsers: assume file exists
}
//}}}
//{{{
if (config.macros.attach.getAttachment==undefined) config.macros.attach.getAttachment=function(title) {
// extract embedded data, local and remote links (if any)
var text=store.getTiddlerText(title,'');
var embedded=store.getTiddlerText(title+'##data','').trim();
var locallink=store.getTiddlerText(title+'##file','').trim();
var remotelink=store.getTiddlerText(title+'##url','').trim();
// backward-compatibility for older attachments (pre 4.0.0)
var startmarker="---BEGIN_DATA---\n";
var endmarker="\n---END_DATA---";
var pos=0; var endpos=0;
if ((pos=text.indexOf(startmarker))!=-1 && (endpos=text.indexOf(endmarker))!=-1)
embedded="data:"+(text.substring(pos+startmarker.length,endpos)).replace(/\n/g,'');
if ((pos=text.indexOf("/%LOCAL_LINK%/"))!=-1)
locallink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));
if ((pos=text.indexOf("/%REMOTE_LINK%/"))!=-1)
remotelink=text.substring(text.indexOf("|",pos)+1,text.indexOf("]]",pos));
// if there is a data: URI defined (not supported by IE)
if (embedded.length && !config.browser.isIE) return embedded;
// document is being served remotely... use remote URL (if any) (avoids security alert)
if (remotelink.length && document.location.protocol!="file:")
return remotelink;
// local link only... return link without checking file existence (avoids security alert)
if (locallink.length && !remotelink.length)
return locallink;
// local link, check for file exist... use local link if found
if (locallink.length) {
locallink=locallink.replace(/^\.[\/\\]/,''); // strip leading './' or '.\' (if any)
if (this.fileExists(getLocalPath(locallink))) return locallink;
// maybe local link is relative... add path from current document and try again
var pathPrefix=document.location.href; // get current document path and trim off filename
var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\");
if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
if (this.fileExists(getLocalPath(pathPrefix+locallink))) return locallink;
}
// no embedded data, no local (or not found), fallback to remote URL (if any)
if (remotelink.length) return remotelink;
// attachment URL doesn't resolve, just return input as is
return title;
}
//}}}
//{{{
if (config.macros.attach.init_formatters==undefined) config.macros.attach.init_formatters=function() {
if (this.initialized) return;
// find the formatter for "image" and replace the handler
for (var i=0; i<config.formatters.length && config.formatters[i].name!="image"; i++);
if (i<config.formatters.length) config.formatters[i].handler=function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link
{
var e = w.output;
if(lookaheadMatch[5])
{
var link = lookaheadMatch[5];
// ELS -------------
var external=config.formatterHelpers.isExternalLink(link);
if (external)
{
if (config.macros.attach.isAttachment(link))
{
e = createExternalLink(w.output,link);
e.href=config.macros.attach.getAttachment(link);
e.title = config.macros.attach.linkTooltip + link;
}
else
e = createExternalLink(w.output,link);
}
else
e = createTiddlyLink(w.output,link,false,null,w.isStatic);
// ELS -------------
addClass(e,"imageLink");
}
var img = createTiddlyElement(e,"img");
if(lookaheadMatch[1])
img.align = "left";
else if(lookaheadMatch[2])
img.align = "right";
if(lookaheadMatch[3])
img.title = lookaheadMatch[3];
img.src = lookaheadMatch[4];
// ELS -------------
if (config.macros.attach.isAttachment(lookaheadMatch[4]))
img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);
// ELS -------------
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
//}}}
//{{{
// find the formatter for "prettyLink" and replace the handler
for (var i=0; i<config.formatters.length && config.formatters[i].name!="prettyLink"; i++);
if (i<config.formatters.length) {
config.formatters[i].handler=function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var e;
var text = lookaheadMatch[1];
if(lookaheadMatch[3]) {
// Pretty bracketted link
var link = lookaheadMatch[3];
if (config.macros.attach.isAttachment(link)) {
e = createExternalLink(w.output,link);
e.href=config.macros.attach.getAttachment(link);
e.title=config.macros.attach.linkTooltip+link;
}
else e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link))
? createExternalLink(w.output,link)
: createTiddlyLink(w.output,link,false,null,w.isStatic);
} else {
e = createTiddlyLink(w.output,text,false,null,w.isStatic);
}
createTiddlyText(e,text);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
} // if "prettyLink" formatter found
this.initialized=true;
}
//}}}
//{{{
config.macros.attach.init_formatters(); // load time init
//}}}
//{{{
if (TiddlyWiki.prototype.coreGetRecursiveTiddlerText==undefined) {
TiddlyWiki.prototype.coreGetRecursiveTiddlerText = TiddlyWiki.prototype.getRecursiveTiddlerText;
TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth) {
return config.macros.attach.isAttachment(title)?
config.macros.attach.getAttachment(title):this.coreGetRecursiveTiddlerText.apply(this,arguments);
}
}
//}}}
Back Bay Large Installation System Administration. See http://www.bblisa.org.
Replace this text with links to tiddlers.
<<matchTags inline "* %0" "\n" sort:title chapter>>
This is the rss feed for new content changes from <<tiddler "GettingStarted::courseHomeRss">>.
<<rssReader noDesc {{store.getTiddlerSlice('GettingStarted', 'courseHomeRss');}} >>
/***
|Name|CopyTiddlerPlugin|
|Source|http://www.TiddlyTools.com/#CopyTiddlerPlugin|
|Version|3.2.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.3|
|Type|plugin|
|Requires||
|Overrides||
|Description|Quickly create a copy of any existing tiddler|
!!!Usage
<<<
The plugin automatically updates the default (shadow) ToolbarCommands definitions to insert the ''copyTiddler'' command, which will appear as ''copy'' when a tiddler is rendered. If you are already using customized toolbar definitions, you will need to manually add the ''copyTiddler'' toolbar command to your existing ToolbarCommands tiddler, e.g.:
{{{
|EditToolbar|... copyTiddler ... |
}}}
When the ''copy'' command is selected, a new tiddler is created containing an exact copy of the current text/tags/fields, using a title of "{{{TiddlerName (n)}}}", where ''(n)'' is the next available number (starting with 1, of course). If you copy while //editing// a tiddler, the current values displayed in the editor are used (including any changes you may have already made to those values), and the new tiddler is immediately opened for editing.
The plugin also provides a macro that allows you to embed a ''copy'' command directly in specific tiddler content:
{{{
<<copyTiddler TidderName label:"..." prompt:"...">>
}}}
where
* ''TiddlerName'' (optional)<br>specifies the //source// tiddler to be copied. If omitted, the current containing tiddler (if any) will be copied.
* ''label:"..."'' (optional)<br>specifies text to use for the embedded link (default="copy TiddlerName")
* ''prompt:"..."'' (optional)<br>specifies mouseover 'tooltip' help text for link
//Note: to use non-default label/prompt values with the current containing tiddler, use "" for the TiddlerName//
<<<
!!!Configuration
<<<
<<option chkCopyTiddlerDate>> use date/time from existing tiddler (otherwise, use current date/time)
{{{<<option chkCopyTiddlerDate>>}}}
<<<
!!!Revisions
<<<
2009.06.08 [3.2.5] added option to use timestamp from source tiddler
2009.03.09 [3.2.4] fixed IE-specific syntax error
2009.03.02 [3.2.3] refactored code (again) to restore use of config.commands.copyTiddler.* custom settings
2009.02.13 [3.2.2] in click(), fix calls to displayTiddler() to use current tiddlerElem and use getTiddlerText() to permit copying of shadow tiddler content
2009.01.30 [3.2.1] fixed handling for copying field values when in edit mode
2009.01.23 [3.2.0] refactored code and added {{{<<copyTiddler TiddlerName>>}}} macro
2008.12.18 [3.1.4] corrected code for finding next (n) value when 'sparse' handling is in effect (thanks to RussThomas for identifying and diagnosing the problem)
2008.11.14 [3.1.3] added optional 'sparse' setting (avoids 'filling in' missing numbers that may have been previously deleted)
2008.11.14 [3.1.2] added optional 'zeroPad' setting
2008.11.14 [3.1.1] moved hard-coded '(n)' regex into 'suffixPattern' object property so it can be customized
2008.09.26 [3.1.0] changed new title generation to use '(n)' suffix instead of 'Copy of' prefix
2008.05.20 [3.0.3] in handler, when copying from VIEW mode, create duplicate array from existing tags array before saving new tiddler.
2007.12.19 [3.0.2] in handler, when copying from VIEW mode, duplicate custom fields before saving new tiddler. Thanks to bug report from Ken Girard.
2007.09.26 [3.0.1] in handler, use findContainingTiddler(src) to get tiddlerElem (and title). Allows 'copy' command to find correct tiddler when transcluded using {{{<<tiddler>>}}} macro or enhanced toolbar inclusion (see [[CoreTweaks]])
2007.06.28 [3.0.0] complete re-write to handle custom fields and alternative view/edit templates
2007.05.17 [2.1.2] use store.getTiddlerText() to retrieve tiddler content, so that SHADOW tiddlers can be copied correctly when in VIEW mode
2007.04.01 [2.1.1] in copyTiddler.handler(), fix check for editor fields by ensuring that found field actually has edit=='text' attribute
2007.02.05 [2.1.0] in copyTiddler.handler(), if editor fields (textfield and/or tagsfield) can't be found (i.e., tiddler is in VIEW mode, not EDIT mode), then get text/tags values from stored tiddler instead of active editor fields. Allows use of COPY toolbar directly from VIEW mode (based on a request from LaurentCharles)
2006.12.12 [2.0.0] completely rewritten so plugin just creates a new tiddler EDITOR with a copy of the current tiddler EDITOR contents, instead of creating the new tiddler in the STORE by copying the current tiddler values from the STORE.
2005.xx.xx [1.0.0] original version by Tim Morgan
<<<
!!!Code
***/
//{{{
version.extensions.CopyTiddlerPlugin= {major: 3, minor: 2, revision: 5, date: new Date(2009,6,8)};
// automatically tweak shadow EditTemplate to add 'copyTiddler' toolbar command (following 'cancelTiddler')
config.shadowTiddlers.ToolbarCommands=config.shadowTiddlers.ToolbarCommands.replace(/cancelTiddler/,'cancelTiddler copyTiddler');
if (config.options.chkCopyTiddlerDate===undefined) config.options.chkCopyTiddlerDate=false;
config.commands.copyTiddler = {
text: 'copy',
hideReadOnly: true,
tooltip: 'Make a copy of this tiddler',
notitle: 'this tiddler',
prefix: '',
suffixText: ' (%0)',
suffixPattern: / \(([0-9]+)\)$/,
zeroPad: 0,
sparse: false,
handler: function(event,src,title)
{ return config.commands.copyTiddler.click(src,event); },
click: function(here,ev) {
var tiddlerElem=story.findContainingTiddler(here);
var template=tiddlerElem?tiddlerElem.getAttribute('template'):null;
var title=here.getAttribute('from');
if (!title || !title.length) {
if (!tiddlerElem) return false;
else title=tiddlerElem.getAttribute('tiddler');
}
var root=title.replace(this.suffixPattern,''); // title without suffix
// find last matching title
var last=title;
if (this.sparse) { // don't fill-in holes... really find LAST matching title
var tids=store.getTiddlers('title','excludeLists');
for (var t=0; t<tids.length; t++) if (tids[t].title.startsWith(root)) last=tids[t].title;
}
// get next number (increment from last matching title)
var n=1; var match=this.suffixPattern.exec(last); if (match) n=parseInt(match[1])+1;
var newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]);
// if not sparse mode, find the next hole to fill in...
while (store.tiddlerExists(newTitle)||document.getElementById(story.idPrefix+newTitle))
{ n++; newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]); }
if (!story.isDirty(title)) { // if tiddler is not being EDITED
// duplicate stored tiddler (if any)
var text=store.getTiddlerText(title,'');
var who=config.options.txtUserName;
var when=new Date();
var newtags=[]; var newfields={};
var tid=store.getTiddler(title); if (tid) {
if (config.options.chkCopyTiddlerDate) var when=tid.modified;
for (var t=0; t<tid.tags.length; t++) newtags.push(tid.tags[t]);
store.forEachField(tid,function(t,f,v){newfields[f]=v;},true);
}
store.saveTiddler(newTitle,newTitle,text,who,when,newtags,newfields,true);
story.displayTiddler(tiddlerElem,newTitle,template);
} else {
story.displayTiddler(tiddlerElem,newTitle,template);
var fields=config.commands.copyTiddler.gatherFields(tiddlerElem); // get current editor fields
var newTiddlerElem=document.getElementById(story.idPrefix+newTitle);
for (var f=0; f<fields.length; f++) { // set fields in new editor
if (fields[f].name=='title') fields[f].value=newTitle; // rename title in new tiddler
var fieldElem=config.commands.copyTiddler.findField(newTiddlerElem,fields[f].name);
if (fieldElem) {
if (fieldElem.getAttribute('type')=='checkbox')
fieldElem.checked=fields[f].value;
else
fieldElem.value=fields[f].value;
}
}
}
story.focusTiddler(newTitle,'title');
return false;
},
findField: function(tiddlerElem,field) {
var inputs=tiddlerElem.getElementsByTagName('input');
for (var i=0; i<inputs.length; i++) {
if (inputs[i].getAttribute('type')=='checkbox' && inputs[i].field == field) return inputs[i];
if (inputs[i].getAttribute('type')=='text' && inputs[i].getAttribute('edit') == field) return inputs[i];
}
var tas=tiddlerElem.getElementsByTagName('textarea');
for (var i=0; i<tas.length; i++) if (tas[i].getAttribute('edit') == field) return tas[i];
var sels=tiddlerElem.getElementsByTagName('select');
for (var i=0; i<sels.length; i++) if (sels[i].getAttribute('edit') == field) return sels[i];
return null;
},
gatherFields: function(tiddlerElem) { // get field names and values from current tiddler editor
var fields=[];
// get checkboxes and edit fields
var inputs=tiddlerElem.getElementsByTagName('input');
for (var i=0; i<inputs.length; i++) {
if (inputs[i].getAttribute('type')=='checkbox')
if (inputs[i].field) fields.push({name:inputs[i].field,value:inputs[i].checked});
if (inputs[i].getAttribute('type')=='text')
if (inputs[i].getAttribute('edit')) fields.push({name:inputs[i].getAttribute('edit'),value:inputs[i].value});
}
// get textareas (multi-line edit fields)
var tas=tiddlerElem.getElementsByTagName('textarea');
for (var i=0; i<tas.length; i++)
if (tas[i].getAttribute('edit')) fields.push({name:tas[i].getAttribute('edit'),value:tas[i].value});
// get selection lists (droplist or listbox)
var sels=tiddlerElem.getElementsByTagName('select');
for (var i=0; i<sels.length; i++)
if (sels[i].getAttribute('edit')) fields.push({name:sels[i].getAttribute('edit'),value:sels[i].value});
return fields;
}
};
//}}}
// // MACRO DEFINITION
//{{{
config.macros.copyTiddler = {
label: 'copy',
prompt: 'Make a copy of %0',
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var title=params.shift();
params=paramString.parseParams('anon',null,true,false,false);
var label =getParam(params,'label',this.label+(title?' '+title:''));
var prompt =getParam(params,'prompt',this.prompt).format([title||this.notitle]);
var b=createTiddlyButton(place,label,prompt,
function(ev){return config.commands.copyTiddler.click(this,ev)});
b.setAttribute('from',title||'');
}
};
//}}}
! Copyright
All tiddlers marked with the structure or content tags are copyrighted © by the author.
! Additional licenses
Parts of this coursebook use components that are licensed separately from the content. This section contains the license information under which they are made available, or permission from the author to use the component.
!! ~TiddlyWiki license
From: http://tiddlywiki.org/wiki/TiddlyWiki_License
{{{
TiddlyWiki created by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
Copyright (c) UnaMesa Association 2004-2008
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of the UnaMesa Association nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
}}}
!! ~TiddlySaver.jar License
From http://www.mail-archive.com/tiddlywiki@googlegroups.com/msg07643.html:
{{{
[tw] Re: Can TiddlyWiki and TiddlySaver.jar be redistributed? Licensing and copyright questions.
Jeremy Ruston
Sat, 01 Aug 2009 11:55:02 -0700
For licensing purposes TiddlySaver is intended to be considered to be
a component of TiddlyWiki, and available under the same terms.
Cheers
Jerm
}}}
!! Plugins from tiddlytools.com
All the plugins/scripts from tiddlytools.com are covered by http://www.tiddlytools.com/#LegalStatements.
<<<
This work is based upon TiddlyWiki <<version>>, written by Jeremy Ruston, © [[UnaMesa Association|http://www.unamesa.org/]] 2004-2008.
Modifications and additions to this work, including (but not limited to) original programmatic components ("plugins", "macros", "scripts", "stylesheets") have been created by Eric L. Shulman and/or ELS Design Studios. These components are currently distributed using an ''open source'' model; however, they are ''not in the public domain'', and the author ''retains all applicable rights''. Nonetheless, you //are// permitted to ''use, copy, and/or modify'' individual components of this work, subject to the licensing ''terms and conditions'' specifically included within or referenced by those individual components, as well as other terms, conditions, instructions, and guidelines included herein or by reference to the [[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]].
This work may contain portions of copyrighted materials from other sources. In accordance with "fair use" principles (see [[United States Copyright Law, Title 17, Section 107|http://www.copyright.gov/title17/92chap1.html#107]]), such materials have been reproduced without profit for purposes of criticism, comment, news reporting, instruction, scholarship, and/or research. ''All other original content, including (but not limited to) writings, illustrations, photographic images, sound recordings, and videos, are the property of Eric L. Shulman and/or ELS Design Studios, or are used under license or agreement with third parties'' and, except as required for normative operation and viewing of this work, may not be stored, displayed or re-transmitted in any form, nor used for any commercial purposes, without the specific prior permission of the respective rights holders.
This work includes or makes reference to icons that are part of the [["Silk" icon set|http://www.famfamfam.com/lab/icons/silk/ ]] containing 1000 16-by-16 pixel icons in PNG format, created by Mark James, and is licensed under a Creative Commons Attribution 2.5 License. Please visit http://www.famfamfam.com/ for further information and licensing details regarding this icon set.
''Terms of use:''
This work contains ''individual components that are intended to be selectively copied and installed'' into your own TiddlyWiki files in order to enhance and customize those documents. You may not re-distribute this document in it's entirety, nor re-use it's overall design without specific prior permission. You may, however, ''download and save this work for use only as a //local// resource'' to assist you in developing your //own// TiddlyWiki document designs.
Because people can import plugins from anyone's TiddlyWiki document, as soon as you share your document with just ONE other person, you become a "re-distributor" of the components you have installed in that document. As such, ''you should avoid modifying any ~TiddlyTools components you have installed in your own documents'' unless there is a compelling, //functional// reason to do so and, even then, ''the best approach is often to simply submit a feature request'' to the original author/publisher and leave it up to them to determine the best way to modify and re-publish their components.
Nonetheless, if you //do// modify and/or share components of this work, you should ''always retain the original published content within those those components'', including all documentation, credits, licensing information, and URL references to the official distribution source for the unaltered versions of those components. In addition, ''all modified components must be clearly identifiable as derivative works'' that have been differentiated from the original versions by renaming those components, as well as adding inline comments and a "revision history" to document specific changes.
If you share a modified ~TiddlyTools component, you must be prepared to support it. All ''problems that occur within a modified component should be reported first directly to the provider of that modified component'', and then only reported to ~TiddlyTools if it can be shown that the problem also occurs in ~TiddlyTools' officially-published version of the component. Any ''problems that are reported for //undifferentiated// modifications won't receive help from ~TiddlyTools'' (once they are determined to be modified, of course!), other than to direct the inquiry to wherever they got the modified components from in the first place.
Except for officially-published links to specific components of this work, ''you must not create or share deep links'' to online components of this work (e.g., images, audio, video, etc.). Instead, you should copy the desired components (subject to applicable licenses and copyrights) to your own system or online hosting service, and ensure that your document contains references to //those// copies.
''Trademarks/servicemarks:''
"ELS Design Studios", "~TiddlyTools", "~TiddlyStudios", "~TiddlyTech", "~TiddlyLabs", "Small Tools for Big Ideas!", "Intuitive Interfaces for Intelligent Interactions" and the "i4" logo (in graphical //and// text forms) are trademarks or servicemarks of ELS Design Studios and may not be used without permission. Limited use of "ELS Design Studios" and "~TiddlyTools" marks in other works is granted for attribution purposes only. Such use does not create or imply any endorsement, agency or partner relationship with Eric L. Shulman and/or ELS Design Studios, nor with any designated representatives, agents, or heirs thereof.
''Limits on Liability:''
All materials are presented on an "as-is" basis and are subject to change without notice. The author of this document makes no claims regarding the suitability or reliability of the information presented, and assumes no liability for any damages that may occur as a result of its use.
''Privacy Notice: ''
This site limits the collection and use of non-public, personal customer information to that which is needed to offer products and services, and to file reports or financial statements as required by law. This site has physical, electronic and procedural safeguards to maintain the protections of private information, and does not provide, sell or otherwise disclose such information to non-affiliated third parties.
<<<
!! Plugins from tiddlywiki.bidx.info
Licensed under BSD open source license. http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D
!! Plugins from tw.lewcid.org
Plugins created by Saq Imtiaz are covered under the creative commons license: http://creativecommons.org/licenses/by-sa/3.0/ license.
!! Plugins from tiddlywiki.abego-software.de
Are licensed under the Bsd License that is referenced from the plugin and is located at:
http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D
!! Paulo Soares plugins
http://www.math.ist.utl.pt/~psoares/addons.html licensed under http://creativecommons.org/licenses/by-sa/3.0/
!! ~Clint Checketts and Paul Petterson
RedirectMacro - Multiple attempts to contact the author have failed. From this thread:
<<<
http://groups.google.com/group/tiddlywiki/browse_thread/thread/2e65045b53d231cf/efc9861ded20605e?q=redirect#efc9861ded20605e
<<<
it appears to be abandoned. As a result it falls into the public domain.
!! TiddlyLockPlugin
http://creativecommons.org/licenses/by-sa/3.0/
!! RefreshCommand
Email addresses were changed to prevent harvesting.
{{{
From: Simon Baird <simon.baird at gmail dot .com>
Subject: Re: Rights to redistribute the RefreshCommand
--0016e64bd5bc00cdad0471eff216
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Please go ahead.
License details for my TW related plugins:
http://mptw.tiddlyspot.com/#License%20TheBSDLicense
On Tue, Aug 25, 2009 at 2:23 PM, John P. Rouillard <[[redacted]]>wrote:
>
> Hello Mr. Baird:
>
> I am developing a TiddlyWiki for use in a class I am teaching. I
> would like to include your RefreshCommand plugin, however I am unable
> to find any license/copyright for it.
>
> Since the TiddlyWiki will be distributed by the sponsor as part of the
> materials for the course, I need to be able to satisfy them that I
> have the right to redistribute the plugin as part of the course book.
>
> Also I plan on releasing the TiddlyWiki Coursebook for others to use
> and as a result it would include a copy of your plugin.
>
> Do I have your permission to redistribute the plugin?
>
> Thank you for your time.
>
}}}
!! DisplayOpenTiddlersPlugin
{{{
Date: Wed, 26 Aug 2009 14:15:19 -0000
To: rouilj@[[redacted]]
From: shadowman131 at comcast dot net
Subject: Re: Right to redistribute the DisplayOpenTiddlersPlugin
------=_Part_192496_151585835.1251296119472
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Hi John,
You have absolute permission to distribute/modify DisplayOpenTiddlersPlugin as
much as you like. It was very kind of you to ask. Let me know if you happen to
need anything else.
Thanks,
-Walt
----- Original Message -----
From: "John P. Rouillard" <rouilj at cs.umb.edu>
To: shadowman131 at comcast dot .net
Sent: Monday, August 24, 2009 8:48:37 PM GMT -08:00 US/Canada Pacific
Subject: Right to redistribute the DisplayOpenTiddlersPlugin
Hello Mr. Woods:
I am developing a TiddlyWiki for use in a class I am teaching. I
would like to include your DisplayOpenTiddlersPlugin plugin, however I
am unable to find any license/copyright for it.
Since the tiddlywiki will be distributed by the sponsor as part of the
materials for the course, I need to be able to satisfy them that I
have the right to redistribute the plugin as part of the course book.
Also I plan on releasing the TiddlyWiki Coursebook for other to use
and as a result it would include a copy of your plugin.
Do I have your permission to redistribute the plugin?
Thank you for your time.
Sincerely yours,
--
-- rouilj
John Rouillard
}}}
This course has:
<html>
<hide linebreaks>
<ul>
<li class="overlay1">Presentations - instructor led slide shows</li>
<li class="overlay2">Chapters - additional contents that extends the presentations and reference material</li>
<li class="overlay3">Quizzes - usually included in the chapters, these test your knowledge of the material</li>
</ul>
</html>
{{overlay4 {
All three are accessible from the left hand menu
}}}
In normal mode coursebook has a three column layout:
* left - the MainMenu has links to the major components of the coursebook
* center - called the story column (or just story) contains the tiddlers for reading
* right - controls to search, jump to tiddlers, save configure and get additional info
@@display: block;text-align: center;[img(75%,)[Frontscreen.png]]@@
In presentation (slide show) mode the three columns are reduced to one and a slide is shown full screen.
[[ToolIndex]]
[[Welcome]]
The tiddlers marked with DeletedTiddler have been superseded by other tiddlers. To cleanup your coursebook, delete them.
If there are any tiddlers you need to delete, there will be a grey box marked "tagging" on the top left (not to be confused with the "tags" box on the right). You can go through each tiddler and find out why it was deleted and preserve any notes you may have for that tiddler before you delete it.
The following link will delete them automatically, it can not be undone, you will have to reload this tiddlywiki before saving or go to backups to recover the tiddlers.
<script label="Remove the tiddlers marked with DeletedTiddlers">
var tids=store.getTaggedTiddlers('DeletedTiddler'); for (var t=0; t<tids.length; t++) store.deleteTiddler(tids[t].title);
displayMessage('Deleted ' + tids.length + ' tiddlers.');
</script>
After deleting the tiddlers, you need to save the coursebook using the ''save changes'' link in the right hand sidebar. Note that there may not be any indication that the coursebook has changed.
/***
|Name|DisplayOpenTiddlersPlugin|
|Location|http://www.orst.edu/~woodswa/tiddlywikiplugs.html|
|Version|1.0|
|Author|Walt Woods|
|Requirements||
!Description
Displays similar to the popular BreadCrumbsPlugin by AlanHecht, this plugin instead keeps a list of currently open tiddlers.
!History
09-06-2009: JohnRouillard modified seperator between items on tiddler line.
08-06-2007: Initial version.
!Code
***/
//{{{
version.extensions.DisplayOpenTiddlers = {major: 1, minor: 0, revision: 0};
function addOpenTiddlerLine(title, element)
{
if (title != openTiddlerClosing)
{
if (tiddlerLine != "")
tiddlerLine += " • ";
tiddlerLine += "[[" + title + "]]";
}
}
function refreshOpenTiddlersList()
{
if (!document.getElementById("openTiddlers")) {
var ta = document.createElement("div");
ta.id = "openTiddlers";
ta.style.visibility= "hidden";
var targetArea = document.getElementById("tiddlerDisplay")||document.getElementById("storyDisplay");
targetArea.parentNode.insertBefore(ta,targetArea);
}
var tiddlers = document.getElementById("openTiddlers");
tiddlers.style.visibility = "visible";
removeChildren(tiddlers);
tiddlerLine = "";
story.forEachTiddler(addOpenTiddlerLine);
wikify(tiddlerLine,tiddlers)
}
Story.prototype.displayTiddlerDisplayOpenTiddlers = Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
this.displayTiddlerDisplayOpenTiddlers(srcElement,title,template,animate,slowly);
openTiddlerClosing = "";
refreshOpenTiddlersList();
}
Story.prototype.closeTiddlerDisplayOpenTiddlers = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,unused)
{
this.closeTiddlerDisplayOpenTiddlers(title,animate,unused);
openTiddlerClosing = title;
refreshOpenTiddlersList();
}
//}}}
<html>
<hide linebreaks>
<ul>
<li>It's still a beta tool</li>
<li class="overlay1">Single user tool. No collaborative editing.</li>
<li class="overlay2">Formatting is annoying</li>
<li class="overlay3">Printing takes some trial and error</li>
<li class="overlay4">Have to pay attention to the pointer location when generating new items or draging/dropping.</li>
</ul>
</html>
<html>
<hide linebreaks>
<ul>
<li>Logbook - make text immutable immediately or after some period of time</li>
<li class="overlay1">Simple Blogging Platform - supports user registration and validation via email</li>
<li class="overlay2">Basic bug tracker - define fields for severity, state etc.</li>
<li class="overlay3">Small Database - Define fields for items</li>
<li class="overlay4">Personal Notebook - consider it blogging on a stick</li>
<li class="overlay5">File distribution - attach files to notes for other to grab</li>
</ul>
</html>
[[ELOG|https://midas.psi.ch/elog/]] was designed as an online log book for the ~PiBeta and Mugamma particle experiments at PSI.
It can be downloaded from: https://midas.psi.ch/elog/download.html or http://sourceforge.net/projects/elog/.
[[Elog in the Beginning]]
[[Elog Use Cases]]
[[Getting It Running]]
[[Demo]]
[[Some Features]]
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|interactively select/export tiddlers to a separate file|
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2009.09.12 [2.9.4] fixed 'return false' to prevent IE page transitions
2009.07.06 [2.9.3] moved HTML to section for size reduction
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 9, revision: 4, date: new Date(2009,9,12)};
// default shadow definition
config.shadowTiddlers.ExportTiddlers='<<exportTiddlers inline>>';
// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
config.tasks.exportTask = {
text:'export',
tooltip:'Export selected tiddlers to another file',
content:'<<exportTiddlers inline>>'
}
config.backstageTasks.splice(config.backstageTasks.indexOf('importTask')+1,0,'exportTask');
}
config.macros.exportTiddlers = {
$: function(id) { return document.getElementById(id); }, // abbreviation
label: 'export tiddlers',
prompt: 'Copy selected tiddlers to an export document',
okmsg: '%0 tiddlers written to %1',
failmsg: 'An error occurred while creating %1',
mergeprompt: '%0\nalready contains tiddlers.\n'
+'\nPress OK to merge new/revised tiddlers into existing file.'
+'\nor, press Cancel to completely replace the file contents',
mergestatus: 'Merged %0 new/revised tiddlers with %1 previously saved tiddlers',
statusmsg: '%0 tiddler%1 - %2 selected for export',
newdefault: 'export.html',
datetimefmt: '0MM/0DD/YYYY 0hh:0mm:0ss', // for 'filter date/time' edit fields
type_TW: "tw", type_PS: "ps", type_TX: "tx", type_CS: "cs", type_NF: "nf", // file type tokens
type_map: { // maps type param to token values
tiddlywiki:"tw", tw:"tw", wiki: "tw",
purestore: "ps", ps:"ps", store:"ps",
plaintext: "tx", tx:"tx", text: "tx",
comma: "cs", cs:"cs", csv: "cs",
newsfeed: "nf", nf:"nf", xml: "nf", rss:"nf"
},
handler: function(place,macroName,params) {
if (params[0]!='inline')
{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
var panel=this.createPanel(place);
panel.style.position='static';
panel.style.display='block';
},
createPanel: function(place) {
var panel=this.$('exportPanel');
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(store.getTiddlerText('ExportTiddlersPlugin##css',''),'exportTiddlers');
panel=createTiddlyElement(place,'span','exportPanel',null,null)
panel.innerHTML=store.getTiddlerText('ExportTiddlersPlugin##html','');
this.initFilter();
this.refreshList(0);
var fn=this.$('exportFilename');
if (window.location.protocol=='file:' && !fn.value.length) {
// get new target path/filename
var newPath=getLocalPath(window.location.href);
var slashpos=newPath.lastIndexOf('/'); if (slashpos==-1) slashpos=newPath.lastIndexOf('\\');
if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
fn.value=newPath+this.newdefault;
}
return panel;
},
togglePanel: function(e) { var e=e||window.event;
var cme=config.macros.exportTiddlers; // abbrev
var parent=resolveTarget(e).parentNode;
var panel=cme.$('exportPanel');
if (panel==undefined || panel.parentNode!=parent)
panel=cme.createPanel(parent);
var isOpen=panel.style.display=='block';
if(config.options.chkAnimate)
anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,'none'));
else
panel.style.display=isOpen?'none':'block' ;
if (panel.style.display!='none') {
cme.refreshList(0);
cme.$('exportFilename').focus();
cme.$('exportFilename').select();
}
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
},
process: function(which) { // process panel control interactions
var theList=this.$('exportList'); if (!theList) return false;
var count = 0;
var total = store.getTiddlers('title').length;
switch (which.id) {
case 'exportFilter':
count=this.filterExportList();
var panel=this.$('exportFilterPanel');
if (count==-1) { panel.style.display='block'; break; }
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) { alert('No tiddlers were selected'); panel.style.display='block'; }
break;
case 'exportStart':
this.go();
break;
case 'exportDelete':
this.deleteTiddlers();
break;
case 'exportHideFilter':
case 'exportToggleFilter':
var panel=this.$('exportFilterPanel')
panel.style.display=(panel.style.display=='block')?'none':'block';
break;
case 'exportSelectChanges':
var lastmod=new Date(document.lastModified);
for (var t = 0; t < theList.options.length; t++) {
if (theList.options[t].value=='') continue;
var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
theList.options[t].selected=(tiddler.modified>lastmod);
count += (tiddler.modified>lastmod)?1:0;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) alert('There are no unsaved changes');
break;
case 'exportSelectAll':
for (var t = 0; t < theList.options.length; t++) {
if (theList.options[t].value=='') continue;
theList.options[t].selected=true;
count += 1;
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,count);
break;
case 'exportSelectOpened':
for (var t=0; t<theList.options.length; t++) theList.options[t].selected=false;
var tiddlerDisplay=this.$('tiddlerDisplay');
for (var t=0; t<tiddlerDisplay.childNodes.length;t++) {
var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
for (var i=0; i<theList.options.length; i++) {
if (theList.options[i].value!=tiddler) continue;
theList.options[i].selected=true; count++; break;
}
}
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
this.displayStatus(count,total);
if (count==0) alert('There are no tiddlers currently opened');
break;
case 'exportSelectRelated':
// recursively build list of related tiddlers
function getRelatedTiddlers(tid,tids) {
var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
tids.push(t.title);
if (!t.linksUpdated) t.changed();
for (var i=0; i<t.links.length; i++)
if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
return tids;
}
// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
var tids=[];
for (var i=0; i<theList.options.length; i++)
if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
// select related tiddlers (includes original selected tiddlers)
for (var i=0; i<theList.options.length; i++)
theList.options[i].selected=tids.contains(theList.options[i].value);
this.displayStatus(tids.length,total);
break;
case 'exportListSmaller': // decrease current listbox size
var min=5;
theList.size-=(theList.size>min)?1:0;
break;
case 'exportListLarger': // increase current listbox size
var max=(theList.options.length>25)?theList.options.length:25;
theList.size+=(theList.size<max)?1:0;
break;
case 'exportClose':
this.$('exportPanel').style.display='none';
break;
}
return false;
},
displayStatus: function(count,total) {
var txt=this.statusmsg.format([total,total!=1?'s':'',!count?'none':count==total?'all':count]);
clearMessage(); displayMessage(txt);
return txt;
},
refreshList: function(selectedIndex) {
var theList = this.$('exportList'); if (!theList) return;
// get the sort order
var sort;
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) sort='modified';
if (selectedIndex==1) sort='title';
if (selectedIndex==2) sort='modified';
if (selectedIndex==3) sort='modifier';
if (selectedIndex==4) sort='tags';
// unselect headings and count number of tiddlers actually selected
var count=0;
for (var t=5; t < theList.options.length; t++) {
if (!theList.options[t].selected) continue;
if (theList.options[t].value!='')
count++;
else { // if heading is selected, deselect it, and then select and count all in section
theList.options[t].selected=false;
for ( t++; t<theList.options.length && theList.options[t].value!=''; t++) {
theList.options[t].selected=true;
count++;
}
}
}
// disable 'export' and 'delete' buttons if no tiddlers selected
this.$('exportStart').disabled=(count==0);
this.$('exportDelete').disabled=(count==0);
// show selection count
var tiddlers = store.getTiddlers('title');
if (theList.options.length) this.displayStatus(count,tiddlers.length);
// if a [command] item, reload list... otherwise, no further refresh needed
if (selectedIndex>4) return;
// clear current list contents
while (theList.length > 0) { theList.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
theList.options[i++]=
new Option(tiddlers.length+' tiddlers in document', '',false,false);
theList.options[i++]=
new Option(((sort=='title' )?'>':indent)+' [by title]', '',false,false);
theList.options[i++]=
new Option(((sort=='modified')?'>':indent)+' [by date]', '',false,false);
theList.options[i++]=
new Option(((sort=='modifier')?'>':indent)+' [by author]', '',false,false);
theList.options[i++]=
new Option(((sort=='tags' )?'>':indent)+' [by tags]', '',false,false);
// output the tiddler list
switch(sort) {
case 'title':
for(var t = 0; t < tiddlers.length; t++)
theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
break;
case 'modifier':
case 'modified':
var tiddlers = store.getTiddlers(sort);
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
var lastSection = '';
for(var t = 0; t < tiddlers.length; t++) {
var tiddler = tiddlers[t];
var theSection = '';
if (sort=='modified') theSection=tiddler.modified.toLocaleDateString();
if (sort=='modifier') theSection=tiddler.modifier;
if (theSection != lastSection) {
theList.options[i++] = new Option(theSection,'',false,false);
lastSection = theSection;
}
theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
}
break;
case 'tags':
var theTitles = {}; // all tiddler titles, hash indexed by tag value
var theTags = new Array();
for(var t=0; t<tiddlers.length; t++) {
var title=tiddlers[t].title;
var tags=tiddlers[t].tags;
if (!tags || !tags.length) {
if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
theTitles['untagged'].push(title);
}
else for(var s=0; s<tags.length; s++) {
if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
theTitles[tags[s]].push(title);
}
}
theTags.sort();
for(var tagindex=0; tagindex<theTags.length; tagindex++) {
var theTag=theTags[tagindex];
theList.options[i++]=new Option(theTag,'',false,false);
for(var t=0; t<theTitles[theTag].length; t++)
theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
theList.selectedIndex=selectedIndex; // select current control item
this.$('exportStart').disabled=true;
this.$('exportDelete').disabled=true;
this.displayStatus(0,tiddlers.length);
},
askForFilename: function(here) {
var msg=here.title; // use tooltip as dialog box message
var path=getLocalPath(document.location.href);
var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\');
if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
var filetype=this.$('exportFormat').value.toLowerCase();
var defext='html';
if (filetype==this.type_TX) defext='txt';
if (filetype==this.type_CS) defext='csv';
if (filetype==this.type_NF) defext='xml';
var file=this.newdefault.replace(/html$/,defext);
var result='';
if(window.Components) { // moz
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
picker.init(window, msg, nsIFilePicker.modeSave);
var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
thispath.initWithPath(path);
picker.displayDirectory=thispath;
picker.defaultExtension=defext;
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XPSP2 IE only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
s.FilterIndex=defext=='txt'?2:'html'?3:'xml'?4:1;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { // fallback
var result=prompt(msg,path+file);
}
}
return result;
},
initFilter: function() {
this.$('exportFilterStart').checked=false; this.$('exportStartDate').value='';
this.$('exportFilterEnd').checked=false; this.$('exportEndDate').value='';
this.$('exportFilterTags').checked=false; this.$('exportTags').value='';
this.$('exportFilterText').checked=false; this.$('exportText').value='';
this.showFilterFields();
},
showFilterFields: function(which) {
var show=this.$('exportFilterStart').checked;
this.$('exportFilterStartBy').style.display=show?'block':'none';
this.$('exportStartDate').style.display=show?'block':'none';
var val=this.$('exportFilterStartBy').value;
this.$('exportStartDate').value
=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterStartBy') && (val=='other'))
this.$('exportStartDate').focus();
var show=this.$('exportFilterEnd').checked;
this.$('exportFilterEndBy').style.display=show?'block':'none';
this.$('exportEndDate').style.display=show?'block':'none';
var val=this.$('exportFilterEndBy').value;
this.$('exportEndDate').value
=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
if (which && (which.id=='exportFilterEndBy') && (val=='other'))
this.$('exportEndDate').focus();
var show=this.$('exportFilterTags').checked;
this.$('exportTags').style.display=show?'block':'none';
var show=this.$('exportFilterText').checked;
this.$('exportText').style.display=show?'block':'none';
},
getFilterDate: function(val,id) {
var result=0;
switch (val) {
case 'file':
result=new Date(document.lastModified);
break;
case 'other':
result=new Date(this.$(id).value);
break;
default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
var oneday=86400000;
if (id=='exportStartDate')
result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
else
result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
break;
}
return result;
},
filterExportList: function() {
var theList = this.$('exportList'); if (!theList) return -1;
var filterStart=this.$('exportFilterStart').checked;
var val=this.$('exportFilterStartBy').value;
var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
var filterEnd=this.$('exportFilterEnd').checked;
var val=this.$('exportFilterEndBy').value;
var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
var filterTags=this.$('exportFilterTags').checked;
var tags=this.$('exportTags').value;
var filterText=this.$('exportFilterText').checked;
var text=this.$('exportText').value;
if (!(filterStart||filterEnd||filterTags||filterText)) {
alert('Please set the selection filter');
this.$('exportFilterPanel').style.display='block';
return -1;
}
if (filterStart&&filterEnd&&(startDate>endDate)) {
var msg='starting date/time:\n'
msg+=startDate.toLocaleString()+'\n';
msg+='is later than ending date/time:\n'
msg+=endDate.toLocaleString()
alert(msg);
return -1;
}
// if filter by tags, get list of matching tiddlers
// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
// otherwise use getTaggedTiddlers() for simple tag matching
if (filterTags) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var t=fn.apply(store,[tags]);
var tagged=[];
for (var i=0; i<t.length; i++) tagged.push(t[i].title);
}
// scan list and select tiddlers that match all applicable criteria
var total=0;
var count=0;
for (var i=0; i<theList.options.length; i++) {
// get item, skip non-tiddler list items (section headings)
var opt=theList.options[i]; if (opt.value=='') continue;
// get tiddler, skip missing tiddlers (this should NOT happen)
var tiddler=store.getTiddler(opt.value); if (!tiddler) continue;
var sel=true;
if ( (filterStart && tiddler.modified<startDate)
|| (filterEnd && tiddler.modified>endDate)
|| (filterTags && !tagged.contains(tiddler.title))
|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
sel=false;
opt.selected=sel;
count+=sel?1:0;
total++;
}
return count;
},
deleteTiddlers: function() {
var list=this.$('exportList'); if (!list) return;
var tids=[];
for (i=0;i<list.length;i++)
if (list.options[i].selected && list.options[i].value.length)
tids.push(list.options[i].value);
if (!confirm('Are you sure you want to delete these tiddlers:\n\n'+tids.join(', '))) return;
store.suspendNotifications();
for (t=0;t<tids.length;t++) {
var tid=store.getTiddler(tids[t]); if (!tid) continue;
var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
msg+='Removing this tiddler may cause unexpected results. Are you sure?'
if (tid.tags.contains('systemConfig') && !confirm(msg)) continue;
store.removeTiddler(tid.title);
story.closeTiddler(tid.title);
}
store.resumeNotifications();
alert(tids.length+' tiddlers deleted');
this.refreshList(0); // reload listbox
store.notifyAll(); // update page display
},
go: function() {
if (window.location.protocol!='file:') // make sure we are local
{ displayMessage(config.messages.notFileUrlError); return; }
// get selected tidders, target filename, target type, and notes
var list=this.$('exportList'); if (!list) return;
var tids=[]; for (var i=0; i<list.options.length; i++) {
var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
var tid=store.getTiddler(opt.value); if (!tid) continue;
tids.push(tid);
}
if (!tids.length) return; // no tiddlers selected
var target=this.$('exportFilename').value.trim();
if (!target.length) {
displayMessage('A local target path/filename is required',target);
return;
}
var filetype=this.$('exportFormat').value.toLowerCase();
var notes=this.$('exportNotes').value.replace(/\n/g,'<br>');
var total={val:0};
var out=this.assembleFile(target,filetype,tids,notes,total);
var link='file:///'+target.replace(/\\/g,'/');
var samefile=link==decodeURIComponent(window.location.href);
var p=getLocalPath(document.location.href);
if (samefile) {
if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
}
var ok=saveFile(target,out);
displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
},
plainTextHeader:
'Source:\n\t%0\n'
+'Title:\n\t%1\n'
+'Subtitle:\n\t%2\n'
+'Created:\n\t%3 by %4\n'
+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
plainTextTiddler:
'- - - - - - - - - - - - - - -\n'
+'| title: %0\n'
+'| created: %1\n'
+'| modified: %2\n'
+'| edited by: %3\n'
+'| tags: %4\n'
+'- - - - - - - - - - - - - - -\n'
+'%5\n',
plainTextFooter:
'',
newsFeedHeader:
'<'+'?xml version="1.0"?'+'>\n'
+'<rss version="2.0">\n'
+'<channel>\n'
+'<title>%1</title>\n'
+'<link>%0</link>\n'
+'<description>%2</description>\n'
+'<language>en-us</language>\n'
+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
+'<pubDate>%3</pubDate>\n'
+'<lastBuildDate>%3</lastBuildDate>\n'
+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
newsFeedTiddler:
'\n%0\n',
newsFeedFooter:
'</channel></rss>',
pureStoreHeader:
'<html><body>'
+'<style type="text/css">'
+' #storeArea {display:block;margin:1em;}'
+' #storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
+' #pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
+'</style>'
+'<div id="pureStoreHeading">'
+' TiddlyWiki "PureStore" export file<br>'
+' Source'+': <b>%0</b><br>'
+' Title: <b>%1</b><br>'
+' Subtitle: <b>%2</b><br>'
+' Created: <b>%3</b> by <b>%4</b><br>'
+' TiddlyWiki %5 / %6 %7<br>'
+' Notes:<hr><pre>%8</pre>'
+'</div>'
+'<div id="storeArea">',
pureStoreTiddler:
'%0\n%1',
pureStoreFooter:
'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
assembleFile: function(target,filetype,tids,notes,total) {
var revised='';
var now = new Date().toLocaleString();
var src=convertUnicodeToUTF8(document.location.href);
var title = convertUnicodeToUTF8(wikifyPlain('SiteTitle').htmlEncode());
var subtitle = convertUnicodeToUTF8(wikifyPlain('SiteSubtitle').htmlEncode());
var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
var twver = version.major+'.'+version.minor+'.'+version.revision;
var v=version.extensions.ExportTiddlersPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
var headerargs=[src,title,subtitle,now,user,twver,'ExportTiddlersPlugin',pver,notes];
switch (filetype) {
case this.type_TX: // plain text
var header=this.plainTextHeader.format(headerargs);
var footer=this.plainTextFooter;
break;
case this.type_CS: // comma-separated
var fields={};
for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
var names=['title','created','modified','modifier','tags','text'];
for (var f in fields) names.push(f);
var header=names.join(',')+'\n';
var footer='';
break;
case this.type_NF: // news feed (XML)
headerargs[0]=store.getTiddlerText('SiteUrl','');
var header=this.newsFeedHeader.format(headerargs);
var footer=this.newsFeedFooter;
break;
case this.type_PS: // PureStore (no code)
var header=this.pureStoreHeader.format(headerargs);
var footer=this.pureStoreFooter;
break;
case this.type_TW: // full TiddlyWiki
default:
var currPath=getLocalPath(window.location.href);
var original=loadFile(currPath);
if (!original) { displayMessage(config.messages.cantSaveError); return; }
var posDiv = locateStoreArea(original);
if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
var footer = '\n'+original.substr(posDiv[1]);
break;
}
var out=this.getData(target,filetype,tids,fields);
var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
// if full TW, insert page title and language attr, and reset all MARKUP blocks...
if (filetype==this.type_TW) {
var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
revised=updateLanguageAttribute(revised);
var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
revised=updateMarkupBlock(revised,'PRE-HEAD',
titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
revised=updateMarkupBlock(revised,'POST-HEAD',
titles.contains('MarkupPostHead')?'MarkupPostHead':null);
revised=updateMarkupBlock(revised,'PRE-BODY',
titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
revised=updateMarkupBlock(revised,'POST-SCRIPT',
titles.contains('MarkupPostBody')?'MarkupPostBody':null);
}
total.val=out.length;
return revised;
},
getData: function(target,filetype,tids,fields) {
// output selected tiddlers and gather list of titles (for use with merge)
var out=[]; var titles=[];
var url=store.getTiddlerText('SiteUrl','');
for (var i=0; i<tids.length; i++) {
out.push(this.formatItem(store,filetype,tids[i],url,fields));
titles.push(tids[i].title);
}
// if TW or PureStore format, ask to merge with existing tiddlers (if any)
if (filetype==this.type_TW || filetype==this.type_PS) {
var txt=loadFile(target);
if (txt && txt.length) {
var remoteStore=new TiddlyWiki();
if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
if (remoteStore.importTiddlyWiki(txt) && confirm(this.mergeprompt.format([target]))) {
var existing=remoteStore.getTiddlers('title');
for (var i=0; i<existing.length; i++)
if (!titles.contains(existing[i].title))
out.push(this.formatItem(remoteStore,filetype,existing[i],url));
displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
}
}
}
return out;
},
formatItem: function(s,f,t,u,fields) {
if (f==this.type_TW)
var r=s.getSaver().externalizeTiddler(s,t);
if (f==this.type_PS)
var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
if (f==this.type_NF)
var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
if (f==this.type_TX)
var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
if (f==this.type_CS) {
function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
for (var f in fields) out.push(toCSV(t.fields[f]||''));
var r=out.join(',');
}
return r||"";
}
}
//}}}
/***
!!!Control panel CSS
//{{{
!css
#exportPanel {
display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;
background-color: #eee; color:#000; font-size: 8pt; line-height:110%;
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;
padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;
}
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }
#exportPanel table {
width:100%; border:0px; padding:0px; margin:0px;
font-size:8pt; line-height:110%; background:transparent;
}
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }
#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}
#exportPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }
#exportPanel textarea { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }
#exportPanel .box {
border:1px solid black; padding:3px; margin-bottom:5px;
background:#f8f8f8; -moz-border-radius:5px;-webkit-border-radius:5px; }
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }
#exportPanel .rad { width:auto;border:0 }
#exportPanel .chk { width:auto;border:0 }
#exportPanel .btn { width:auto; }
#exportPanel .btn1 { width:98%; }
#exportPanel .btn2 { width:48%; }
#exportPanel .btn3 { width:32%; }
#exportPanel .btn4 { width:24%; }
#exportPanel .btn5 { width:19%; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- target path/file -->
<div>
export to path/filename:<br>
<input type="text" id="exportFilename" size=40 style="width:93%"><input
type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%"
onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">
</div>
<!-- output format -->
<div>
output file format:
<select id="exportFormat" size=1>
<option value="TW">TiddlyWiki HTML document (includes core code)</option>
<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>
<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>
<option value="CS">Comma-Separated Value (CSV) data file</option>
<option value="NF">RSS NewsFeed XML file</option>
</select>
</div>
<!-- notes -->
<div>
notes:<br>
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea>
</div>
<!-- list of tiddlers -->
<table><tr align="left"><td>
select:
<a href="JavaScript:;" id="exportSelectAll"
onclick="return config.macros.exportTiddlers.process(this)" title="select all tiddlers">
all </a>
<a href="JavaScript:;" id="exportSelectChanges"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">
changes </a>
<a href="JavaScript:;" id="exportSelectOpened"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">
opened </a>
<a href="JavaScript:;" id="exportSelectRelated"
onclick="return config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">
related </a>
<a href="JavaScript:;" id="exportToggleFilter"
onclick="return config.macros.exportTiddlers.process(this)" title="show/hide selection filter">
filter </a>
</td><td align="right">
<a href="JavaScript:;" id="exportListSmaller"
onclick="return config.macros.exportTiddlers.process(this)" title="reduce list size">
– </a>
<a href="JavaScript:;" id="exportListLarger"
onclick="return config.macros.exportTiddlers.process(this)" title="increase list size">
+ </a>
</td></tr></table>
<select id="exportList" multiple size="10" style="margin-bottom:5px;"
onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">
</select><br>
<!-- selection filter -->
<div id="exportFilterPanel" style="display:none">
<table><tr align="left"><td>
selection filter
</td><td align="right">
<a href="JavaScript:;" id="exportHideFilter"
onclick="return config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>
</td></tr></table>
<div class="box">
<input type="checkbox" class="chk" id="exportFilterStart" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterStartBy"
onchange="config.macros.exportTiddlers.showFilterFields(this);">
<option value="0">today</option>
<option value="1">yesterday</option>
<option value="7">a week ago</option>
<option value="30">a month ago</option>
<option value="file">file date</option>
<option value="other">other (mm/dd/yyyy hh:mm)</option>
</select>
</td><td width="50%">
<input type="text" id="exportStartDate" onfocus="this.select()"
onchange="config.macros.exportTiddlers.$('exportFilterStartBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">
<select size=1 id="exportFilterEndBy"
onchange="config.macros.exportTiddlers.showFilterFields(this);">
<option value="0">today</option>
<option value="1">yesterday</option>
<option value="7">a week ago</option>
<option value="30">a month ago</option>
<option value="file">file date</option>
<option value="other">other (mm/dd/yyyy hh:mm)</option>
</select>
</td><td width="50%">
<input type="text" id="exportEndDate" onfocus="this.select()"
onchange="config.macros.exportTiddlers.$('exportFilterEndBy').value='other';">
</td></tr></table>
<input type="checkbox" class="chk" id=exportFilterTags value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>
<input type="text" id="exportTags" onfocus="this.select()">
<input type="checkbox" class="chk" id=exportFilterText value="1"
onclick="config.macros.exportTiddlers.showFilterFields(this)"> match titles/tiddler text<br>
<input type="text" id="exportText" onfocus="this.select()">
</div> <!--box-->
</div> <!--panel-->
<!-- action buttons -->
<div style="text-align:center">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportFilter" value="apply filter">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportStart" value="export tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportDelete" value="delete tiddlers">
<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"
id="exportClose" value="close">
</div><!--center-->
!end
//}}}
***/
/***
|Name|ExportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.9.3|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for ExportTiddlersPlugin|
interactively select and extract tiddlers from your ~TiddlyWiki document, and write them into another file, using one of several different file formats:
* ~TiddlyWiki - a complete, stand-alone, standard TiddlyWiki HTML document
* ~PureStore - a small HTML archive file containing tiddler data only (no core code)
* ~PlainText - a simple TXT text file with tiddler source listings
* Comma - a "Comma Separated Value" data/spreadsheet file
* ~NewsFeed - an XML-format file that can be published for RSS syndication.
!!!!!Usage
<<<
{{{
<<exportTiddlers>> (sidebar menu item)
<<exportTiddlers inline>> (embedded control panel)
}}}
Inline control panel (live):
<<exportTiddlers inline>>
Optional "special tiddlers" used by this plugin:
* SiteUrl<br>URL for official server-published version of document being viewed (used in XML export). Default: //none//
<<<
!!!!!Revisions
<<<
2009.07.06 [2.9.3] moved HTML to section for size reduction
2009.07.03 [2.9.2] TW252 fixup: don't call convertUTF8ToUnicode() for local loadFile() I/O
2009.04.30 [2.9.1] custom fields in CSV output
2009.04.19 [2.9.0] added CSV format
2009.02.26 [2.8.5] use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.26 [2.8.3] in go(), if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 [2.8.2] in assembleFile(), make sure that markup block is updated if corresponding Markup* tiddler is exported.
2008.09.19 [2.8.1] in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.11 [2.8.0] extensive code cleanup: moved all global functions inside macro object. Re-wrote file generator and I/O to support TiddlyWiki, PlainText, PureStore, and NewsFeed file formats. Replaced inline 'match tags' code with use of getMatchingTiddlers() from [[MatchTagsPlugin]] (if installed), with fallback to core getTaggedTiddlers() otherwise.
2008.05.27 [2.7.0] added ability to 'merge' with existing export file. Also, revised 'matchTags' functionality to be more robust and more efficient
2008.05.12 [2.6.1] automatically add 'export' task to backstage (moved from BackstageTweaks)
2008.03.10 [2.6.0] added "delete tiddlers" button
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.11.10 [2.5.1] removed debugging alert messages from promptForExportFilename()
2007.10.31 [2.5.0] code reduction: removed incomplete/unused interface and supporting functions for exporting directly to http, https or ftp servers. Plugin now supports exporting to local file only. Also, updated TW document output to generate TW2.2 compatible file format.
2007.10.30 [2.4.2] added automatic shadow tiddler definition for [[ExportTiddlers]]
2007.07.16 [2.4.1] in exportTWHeader(), reset HTML source 'markup' so installed markup is NOT copied to new file.
2007.06.30 [2.4.0] added "select related tiddlers" feature. Recursively scans the tiddler links[] info to find all tiddlers referenced by any of the currently selected tiddler, and then selects them all (including the original tiddlers).
2007.04.19 [2.3.0] in exportData(), pass SiteURL value as param to saveToRss(). Fixes 'undefined' appearing in tiddler link in XML output. Also, in refreshExportList(), added 'sort by tags'. Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
2007.03.02 [2.2.6] in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" with fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 [2.2.5] removed hijack of store.saveChanges()
2006.11.08 [2.2.4] added promptForExportFilename() and replaced type="file" control with edit field + browse button ("...").
2006.10.12 [2.2.3] in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format.
2006.05.11 [2.2.2] in createExportPanel, removed call to addNotification() to reduce unneeded feedback messages and increase overall document performance.
2006.05.02 [2.2.1] Use displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection. Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible.
2006.04.29 [2.2.0] New features: free-form "Notes" text inserted in the header of PureStore files.
2006.03.29 [2.1.3] added calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.
2006.02.12 [2.1.2] more FF1501 bug fixes.
2006.02.04 [2.1.1] added var to unintended globals to avoids FireFox1501 crash bug
2006.02.02 [2.1.0] Added support for output of complete TiddlyWiki documents
2006.01.21 [2.0.1] Defer initial panel creation and only register a notification function when panel first is created
in saveChanges 'hijack', create panel as needed. Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.
2005.12.27 [2.0.0] Update for TW2.0.
2005.12.24 [0.9.5] Minor adjustments to CSS to force correct link colors regardless of TW stylesheet selection
2005.12.16 [0.9.4] Dynamically create/remove exportPanel so only one instance exists at a time
2005.11.15 [0.9.2] added non-Ajax post to bypass cross-domain security restrictions.
2005.11.08 [0.9.1] moved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time.
2005.10.28 [0.9.0] added 'select opened tiddlers' feature. Based on a suggestion by Geoff Slocock
2005.10.24 [0.8.3] Corrected hijack of 'save changes' when using http:
2005.10.18 [0.8.2] added AJAX functions
2005.10.18 [0.8.1] Corrected timezone handling and error checking/reporting when filtering tiddlers. More style tweaks, minor text changes and some assorted layout cleanup.
2005.10.17 [0.8.0] First pre-release.
2005.10.16 [0.7.0] filter by tags
2005.10.15 [0.6.0] filter by title/text
2005.10.14 [0.5.0] export to local file (DIV or XML)
2005.10.14 [0.4.0] filter by start/end date
2005.10.13 [0.3.0] panel interaction
2005.10.11 [0.2.0] panel layout
2005.10.10 [0.1.0] code framework
2005.10.09 [0.0.0] development started
<<<
/%
|Description|Saving changes for online documents if the network goes down|
%/
{{small{
__Saving changes to online documents if your network connection goes down while editing__
If you have been editing a document online (e.g., using an account on http://www.TiddlySpot.com with [[UploadPlugin]]), and your internet connection has gone down while editing, it is not possible to save your changes in the usual manner because, without the internet, the remotely-stored document is //inaccessible//.
Unfortunately, you also cannot save the document locally because of security restrictions that prevent access to your local filesystem when working with a server-hosted document (i.e., viewed via http:).
Fortunately, there is a ''manual work-around that will let you 'rescue' TiddlyWiki's internal //storeArea// for the current document, including your unsaved changes to tiddler content'' by using the following command link:
{{big center{<<tiddler RescueStoreAreaCommand with: "rescue storeArea">>}}}
When clicked, this link ''opens a new window and writes a copy of the storeArea into that window.'' The content in that window is displayed as plain-text, and includes //only the storeArea DIVs that define the tiddlers, without any of the surrounding TiddlyWiki core code.// To preserve this storeArea, ''select and copy/paste the displayed content into a local text file for safe-keeping.''
Then, to merge this 'rescued store area' with the rest of the TW core, use a plain-text editor (not the browser) to open a ''copy'' of any locally-stored TW document. If a locally-stored TiddlyWiki document is not available, you will have to wait until your network connection has been re-established, so that you can download your TiddlyWiki document from the server, or [[obtain an empty TiddlyWiki document from http://www.TiddlyWiki.com|http://www.TiddlyWiki.com/empty.html]].
Then, find the 'storeArea' in that document, which looks like this:
{{{
<!--POST-SHADOWAREA-->
<div id="storeArea">
.... *** replace this part *** ...
</div>
<!--POST-STOREAREA-->
}}}
Select everything //inside the storeArea DIV//, and replace it with the rescued store area content, and then save the file. If all goes well, the saved file can then be opened in your browser as a complete TW document, *with* all the saved content in place!
Note: The command link shown above may also be installed directly into your browser as an [[InstantBookmarklet|InstantBookmarklets]]. To create a bookmarklet, simply ''//drag-and-drop the command link directly onto your browser's toolbar//'' or right-click and use 'bookmark this link' (or 'add to favorites') to add the bookmarklet to your browser's bookmarks menu. Once installed, you can use this command with //any// TiddlyWiki document, even when [[RescueStoreAreaCommand]] and [[InlineJavascriptPlugin]] have not been installed in that document!
}}}
<html>
<hide linebreaks>
<ul>
<li>Can remap keys to make entering data easier</li>
<li class="overlay1">Generally easy to work with after a little experience</li>
<li class="overlay2">Drag and drop reordering of nodes/branches</li>
<li class="overlay3">Exports to a number of formats: png, pdf, html (foldable/clickable), flash, ODF, java applet ... (13 in all)</li>
<li class="overlay4">Map is stored in XML format</li>
</ul>
</html>
<html>
<hide linebreaks>
<ul>
<li>Easier to use than M4</li>
<li class="overlay1">Doesn't leave messy blank lines and compiler specific info in files like cpp</li>
<li class="overlay2">Permits use of Perl expressions in conditionals (so you can use regular expressions for example)</li>
<li class="overlay3">Supports looping</li>
<li class="overlay4">Written in Perl so you can develop modules to perform other actions</li>
</ul>
</html>
<html>
<hide linebreaks>
<ul>
<li>Create a website with a consistent look and feel</li>
<li class="overlay1">Generate configuration files that are 90% identical except for certain parameters</li>
<li class="overlay2">Enhance the configuration language of a tool you use</li><ul>
<li class="overlay3">Define new commands</li>
<li class="overlay4">Allow looping in your config files rather than adding a ton of identical statements</li></ul>
<li class="overlay5">Define things once and incorporate them into documentation and code</li>
</ul>
</html>
[[What is a Macro Processor]]
[[What is Filepp]]
[[Filepp Uses]]
[[Filepp Benefits]]
[[Simple Example]]
[[Sample Language Enhancement]]
/***
|''Name:''|FootnotesPlugin|
|''Description:''|Create automated tiddler footnotes.|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#FootnotesPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.01|
|''Date:''|10/25/07|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.2|
!!Usage:
*To create a footnote, just put the footnote text inside triple backticks.
*Footnotes are numbered automatically, and listed at the bottom of the tiddler.
*{{{Creating a footnote is easy. ```This is the text for my footnote```}}}
*[[Example|FootnotesDemo]]
***/
// /%
//!BEGIN-PLUGIN-CODE
config.footnotesPlugin = {
backLabel: "back",
prompt:"show footnote"
};
config.formatters.unshift( {
name: "footnotes",
match: "```",
lookaheadRegExp: /```((?:.|\n)*?)```/g,
handler: function(w)
{
// rouilj to prevent function from erroring when rendered during an rss export operation
// just exit if not being rendered within a story.
if (!story.findContainingTiddler(place)) return;
// end patch
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart )
{
var tiddler = story.findContainingTiddler(w.output);
if (!tiddler.notes)
tiddler.notes = [];
var title = tiddler.getAttribute("tiddler");
tiddler.notes.pushUnique(lookaheadMatch[1]);
var pos = tiddler.notes.indexOf(lookaheadMatch[1]) + 1;
createTiddlyButton(w.output,pos,config.footnotesPlugin.prompt,function(){var x = document.getElementById(title+"ftn"+pos);window.scrollTo(0,ensureVisible(x)+(ensureVisible(x)<findScrollY()?(findWindowHeight()-x.offsetHeight):0));return false;},"ftnlink",title+"ftnlink"+pos);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
});
old_footnotes_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template,force)
{
var tiddler = old_footnotes_refreshTiddler.apply(this,arguments);
if (tiddler && tiddler.notes && tiddler.notes.length)
{
var holder = createTiddlyElement(null,"div",null,"footnoteholder");
var list = createTiddlyElement(holder,"ol",title+"footnoteholder");
for (var i=0; i<tiddler.notes.length; i++)
{
var ftn = createTiddlyElement(list,"li",title+"ftn"+(i+1),"footnote");
wikify(tiddler.notes[i]+" ",ftn);
createTiddlyButton(ftn,"["+config.footnotesPlugin.backLabel+"]",config.footnotesPlugin.backLabel,function(){window.scrollTo(0,ensureVisible(document.getElementById(this.parentNode.id.replace("ftn","ftnlink"))));return false;},"ftnbklink");
}
var count = tiddler.childNodes.length;
for (var j=0; j<count; j++){
if(hasClass(tiddler.childNodes[j],"viewer")){
var viewer = tiddler.childNodes[j];
}
}
viewer.appendChild(holder);
tiddler.notes = [];
}
return tiddler;
};
setStylesheet(
".tiddler a.ftnlink {vertical-align: super; font-size: 0.8em; color:red;}\n"+
".tiddler a.ftnlink:hover, .tiddler .footnoteholder a.ftnbklink:hover{color:#fff;background:red;}\n"+
".tiddler div.footnoteholder{margin:1.8em 1.0em; padding:0.1em 1.0em 0.1em 1.0em ;border-left: 1px solid #ccc;}"+
".tiddler footnoteholder ol {font-size: 0.9em; line-height: 1.2em;}\n"+
".tiddler .footnoteholder li.footnote {margin: 0 0 5px 0;}\n"+
".tiddler .footnoteholder a.ftnbklink{color:red;}\n","FootNotesStyles");
//!END-PLUGIN-CODE
// %/
There are a bunch of GTD supporting verticals:
;~GTDTiddlyWiki
:http://nathanbowers.com/gtdtw/ - the original one from 2005
;gtd_tiddlywiki
:http://www.checkettsweb.com/tw/gtd_tiddlywiki.htm - a newer release with updated core
;~MonkeyGTD
:http://monkeygtd.tiddlyspot.com - a newer release supporting realms (e.g. work and personal, you and your spouse ...). See also: http://wiki.43folders.com/index.php/Monkey_GTD
;D3
:http://www.dcubed.ca/Welcome_to_d-cubed.html - to download samples and blanks to work in. See also: http://wiki.43folders.com/index.php/D3
;tbGTD
:http://tbgtd.tiddlyspot.com/ - yet another entry into the fray
;tiddlyDu3
:http://www.giffmex.org/tiddlydu3.html - another take on GTD
!Inline Formatting
|!Option|!Syntax|!Output|
|bold font|{{{''bold''}}}|''bold''|
|italic type|{{{//italic//}}}|//italic//|
|underlined text|{{{__underlined__}}}|__underlined__|
|strikethrough text|{{{--strikethrough--}}}|--strikethrough--|
|superscript text|{{{^^super^^script}}}|^^super^^script|
|subscript text|{{{~~sub~~script}}}|~~sub~~script|
|highlighted text|{{{@@highlighted@@}}}|@@highlighted@@|
|preformatted text|<html><code>{{{preformatted}}}</code></html>|{{{preformatted}}}|
!Block Elements
!!Headings
{{{
!Heading 1
!!Heading 2
!!!Heading 3
!!!!Heading 4
!!!!!Heading 5
}}}
<<<
!Heading 1
!!Heading 2
!!!Heading 3
!!!!Heading 4
!!!!!Heading 5
<<<
!!Lists
{{{
* unordered list, level 1
** unordered list, level 2
*** unordered list, level 3
# ordered list, level 1
## ordered list, level 2
### unordered list, level 3
; definition list, term
: definition list, description
}}}
<<<
* unordered list, level 1
** unordered list, level 2
*** unordered list, level 3
# ordered list, level 1
## ordered list, level 2
### unordered list, level 3
; definition list, term
: definition list, description
<<<
!!Blockquotes
{{{
> blockquote, level 1
>> blockquote, level 2
>>> blockquote, level 3
<<<
blockquote
<<<
}}}
<<<
> blockquote, level 1
>> blockquote, level 2
>>> blockquote, level 3
> blockquote
<<<
!!Preformatted Text
<html><pre>
{{{
preformatted (e.g. code)
}}}
</pre></html>
<<<
{{{
preformatted (e.g. code)
}}}
<<<
!!Tables
{{{
|CssClass|k
|!heading column 1|!heading column 2|
|row 1, column 1|row 1, column 2|
|row 2, column 1|row 2, column 2|
|>|COLSPAN|
|ROWSPAN| … |
|~| … |
|CssProperty:value;…| … |
|caption|c
}}}
''Annotation:''
* The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
* The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
<<<
|CssClass|k
|!heading column 1|!heading column 2|
|row 1, column 1|row 1, column 2|
|row 2, column 1|row 2, column 2|
|>|COLSPAN|
|ROWSPAN| … |
|~| … |
|CssProperty:value;…| … |
|caption|c
<<<
!!Images /% TODO %/
cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
!Hyperlinks
* [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler
** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}
* [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}
** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).
!Custom Styling
* {{{@@CssProperty:value;CssProperty:value;…@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.
* <html><code>{{customCssClass{…}}}</code></html>
* raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> … </html>}}}
!Special Markers
* {{{<br>}}} forces a manual line break
* {{{----}}} creates a horizontal ruler
* [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]
* {{{<<macroName>>}}} calls the respective [[macro|Macros]]
* To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.
* To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{"""WikiWord"""}}}.
[[Mind Mapping]]
[[The FreeMind Tool]]
[[Demo]]
[[Features]]
[[Drawbacks]]
!usage
{{{[img[Frontscreen.png]]}}}
[img[Frontscreen.png]]
!notes
Layout of the coursebook
!type
image/png
!file
./images/Frontscreen.png
!url
http://www.example.com/class/Frontscreen.png
!data
data:image/png;base64,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
!What would you pay for this?
{{overlay1{Well it's free.}}}
{{overlay2{Best of all one single executable, no databases, web servers etc. to deploy.}}}
{{overlay3{Uses a text file for configuration}}}
{{overlay4{Uses files in a directory for storing notes/files}}}
{{overlay5{Pretty standard C, compile under cygwin, linux, solaris, windows...}}}
{{adiv{
<<showWhen window.location.protocol!='file:'>>
You ''MUST'' download the coursebook to your local disk from: <<tiddler "GettingStarted::courseHomeBook">> (using the browser's download/save link mechanism). You are currenty viewing it using http or https and ''can not'' save it while viewing it from the net.
{{adiv{
<<showWhen ! (config.browser.isIE || (navigator.userAgent.indexOf('Firefox') != -1)) >>
You must also download/save to disk <<tiddler "GettingStarted::courseHomeTs">> in the same directory as the coursebook since you are not using Internet Explorer or Firefox.
}}}
}}} {{adiv{
<<showWhen window.location.protocol=='file:'>>
If you are seeing this tiddler when you first load the file, there is no content loaded in your coursebook yet. Follow the directions below to prepare this coursebook.
# Enter your username for signing your edits: <<option txtUserName>>.
# Click the outlined `button' below to load content into this empty book:<br /> <<loadTiddlers "label:Import new content from %0" updates {{store.getTiddlerSlice('GettingStarted','courseHomeContent')}} {{config.options['chkLoadTiddlersShowReport']=false;}} >>.{{aspan{<<showWhenExists Welcome>>@@<br />''Content has been loaded successfully''.@@}}}
# Once the content is loaded (it can take a minute), click on <<saveChanges>> to save the changes.
# Then click to <html><a style="border: 1px solid #DDBB44" onClick="window.location.reload()">reload the page</a></html> or use F5 in your browser.
}}}
/%
Original content of this tiddler is located below.
----
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
%/
/%
Enter the url's for your coursebook here.
The publication directory
courseHome: http://www.example.com/class
The tiddlywiki copy of the studentbook
courseHomeBook: http://www.example.com/class/studentbook.html
The TiddlySaver.jar file
courseHomeTs: http://www.example.com/class/TiddlySaver.jar
The purestore content file
courseHomeContent: http://www.example.com/class/content.html
The published content rss feed
courseHomeRss: http://www.example.com/class/content.xml
%/
/***
|Name|GotoPlugin|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|view any tiddler by entering it's title - displays list of possible matches|
''View a tiddler by typing its title and pressing //enter//.'' As you type, a list of possible matches is displayed. You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press escape to close the listbox to resume typing. When the listbox is not displayed, pressing //escape// clears the current input.
!!!Documentation
>see [[GotoPluginInfo]]
!!!Configuration
<<<
*Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input. //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
*To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
//{{{
config.macros.gotoTiddler.listMaxSize=10; // change this number
//}}}
<<<
!!!Revisions
<<<
2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
|please see [[GotoPluginInfo]] for additional revision details|
2006.05.05 [0.0.0] started
<<<
!!!Code
***/
//{{{
version.extensions.GotoPlugin= {major: 1, minor: 9, revision: 2, date: new Date(2009,5,22)};
// automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");
if (config.options.txtIncrementalSearchMin===undefined) config.options.txtIncrementalSearchMin=3;
config.macros.gotoTiddler= {
listMaxSize: 10,
listHeading: 'Found %0 matching title%1...',
searchItem: "Search for '%0'...",
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
var quiet =params.contains("quiet");
var showlist =params.contains("showlist");
var search =params.contains("search");
params = paramString.parseParams("anon",null,true,false,false);
var instyle =getParam(params,"inputstyle","");
var liststyle =getParam(params,"liststyle","");
var filter =getParam(params,"filter","");
var html=this.html;
var keyevent=window.event?"onkeydown":"onkeypress"; // IE event fixup for ESC handling
html=html.replace(/%keyevent%/g,keyevent);
html=html.replace(/%search%/g,search);
html=html.replace(/%quiet%/g,quiet);
html=html.replace(/%showlist%/g,showlist);
html=html.replace(/%display%/g,showlist?'block':'none');
html=html.replace(/%position%/g,showlist?'static':'absolute');
html=html.replace(/%instyle%/g,instyle);
html=html.replace(/%liststyle%/g,liststyle);
html=html.replace(/%filter%/g,filter);
if (config.browser.isIE) html=this.IEtableFixup.format([html]);
var span=createTiddlyElement(place,'span');
span.innerHTML=html; var form=span.getElementsByTagName("form")[0];
if (showlist) this.fillList(form.list,'',filter,search,0);
},
html:
'<form onsubmit="return false" style="display:inline;margin:0;padding:0">\
<input name=gotoTiddler type=text autocomplete="off" accesskey="G" style="%instyle%"\
title="Enter title text... ENTER=goto, SHIFT-ENTER=search for text, DOWN=select from list"\
onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list,%search%,%showlist%);"\
onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,%quiet%,%search%,%showlist%);">\
<select name=list style="display:%display%;position:%position%;%liststyle%"\
onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
onblur="this.style.display=%showlist%?\'block\':\'none\';"\
%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler,%showlist%);"\
onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this,%showlist%);">\
</select><input name="filter" type="hidden" value="%filter%">\
</form>',
IEtableFixup:
"<table style='width:100%;display:inline;padding:0;margin:0;border:0;'>\
<tr style='padding:0;margin:0;border:0;'><td style='padding:0;margin:0;border:0;'>\
%0</td></tr></table>",
getItems:
function(list,val,filter) {
if (!list.cache || !list.cache.length || val.length<=config.options.txtIncrementalSearchMin) {
// starting new search, fetch and cache list of tiddlers/shadows/tags
list.cache=new Array();
if (filter.length) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var tiddlers=store.sortTiddlers(fn.apply(store,[filter]),'title');
} else
var tiddlers=store.reverseLookup('tags','excludeLists');
for(var t=0; t<tiddlers.length; t++) list.cache.push(tiddlers[t].title);
if (!filter.length) {
for (var t in config.shadowTiddlers) list.cache.pushUnique(t);
var tags=store.getTags();
for(var t=0; t<tags.length; t++) list.cache.pushUnique(tags[t][0]);
}
}
var found = [];
var match=val.toLowerCase();
for(var i=0; i<list.cache.length; i++)
if (list.cache[i].toLowerCase().indexOf(match)!=-1) found.push(list.cache[i]);
return found;
},
getItemSuffix:
function(t) {
if (store.tiddlerExists(t)) return ""; // tiddler
if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
return " (tag)"; // tag
},
fillList:
function(list,val,filter,search,key) {
if (list.style.display=="none") return; // not visible... do nothing!
var indent='\xa0\xa0\xa0';
var found = this.getItems(list,val,filter); // find matching items...
found.sort(); // alpha by title
while (list.length > 0) list.options[0]=null; // clear list
var hdr=this.listHeading.format([found.length,found.length==1?"":"s"]);
list.options[0]=new Option(hdr,"",false,false);
for (var t=0; t<found.length; t++) list.options[list.length]=
new Option(indent+found[t]+this.getItemSuffix(found[t]),found[t],false,false);
if (search)
list.options[list.length]=new Option(this.searchItem.format([val]),"*",false,false);
list.size=(list.length<this.listMaxSize?list.length:this.listMaxSize); // resize list...
list.selectedIndex=key==38?list.length-1:key==40?1:0;
},
keyProcessed:
function(ev) { // utility function
ev.cancelBubble=true; // IE4+
try{event.keyCode=0;}catch(e){}; // IE5
if (window.event) ev.returnValue=false; // IE6
if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
if (ev.stopPropagation) ev.stopPropagation(); // all
return false;
},
inputEscKeyHandler:
function(event,here,list,search,showlist) {
if (event.keyCode==27) {
if (showlist) { // clear input, reset list
here.value=here.defaultValue;
this.fillList(list,'',here.form.filter.value,search,0);
}
else if (list.style.display=="none") // clear input
here.value=here.defaultValue;
else list.style.display="none"; // hide list
return this.keyProcessed(event);
}
return true; // key bubbles up
},
inputKeyHandler:
function(event,here,quiet,search,showlist) {
var key=event.keyCode;
var list=here.form.list;
var filter=here.form.filter;
// non-printing chars bubble up, except for a few:
if (key<48) switch(key) {
// backspace=8, enter=13, space=32, up=38, down=40, delete=46
case 8: case 13: case 32: case 38: case 40: case 46: break; default: return true;
}
// blank input... if down/enter... fall through (list all)... else, and hide or reset list
if (!here.value.length && !(key==40 || key==13)) {
if (showlist) this.fillList(here.form.list,'',here.form.filter.value,search,0);
else list.style.display="none";
return this.keyProcessed(event);
}
// hide list if quiet, or below input minimum (and not showlist)
list.style.display=(!showlist&&(quiet||here.value.length<config.options.txtIncrementalSearchMin))?'none':'block';
// non-blank input... enter=show/create tiddler, SHIFT-enter=search for text
if (key==13 && here.value.length) return this.processItem(event.shiftKey?'*':here.value,here,list,showlist);
// up or down key, or enter with blank input... shows and moves to list...
if (key==38 || key==40 || key==13) { list.style.display="block"; list.focus(); }
this.fillList(list,here.value,filter.value,search,key);
return true; // key bubbles up
},
selectKeyHandler:
function(event,list,editfield,showlist) {
if (event.keyCode==27) // escape... hide list, move to edit field
{ editfield.focus(); list.style.display=showlist?'block':'none'; return this.keyProcessed(event); }
if (event.keyCode==13 && list.value.length) // enter... view selected item
{ this.processItem(list.value,editfield,list,showlist); return this.keyProcessed(event); }
return true; // key bubbles up
},
processItem:
function(title,here,list,showlist) {
if (!title.length) return;
list.style.display=showlist?'block':'none';
if (title=="*") { story.search(here.value); return false; } // do full-text search
if (!showlist) here.value=title;
story.displayTiddler(null,title); // show selected tiddler
return false;
}
}
//}}}
/***
|Name|GotoPluginInfo|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for GotoPlugin|
''View a tiddler by typing its title and pressing //enter//.'' As you type, a list of possible matches is displayed. You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press escape to close the listbox to resume typing. When the listbox is not displayed, pressing //escape// clears the current input.
!!!!!Usage/Examples
<<<
syntax: {{{<<gotoTiddler quiet search inputstyle:... liststyle:... filter:...>>}}}
All parameters are optional.
* ''quiet'' (//keyword//)<br>list will not be automatically display as each character is typed. Use //down// or //enter// to view the list.
* ''showlist'' (//keyword//)<br>list will always be displayed, inline, directly below the input field.
* ''search'' (//keyword//)<br>adds an extra 'command item' to the list that can be used to invoke a full-text search using the entered value. This can be especially useful when no matching tiddler titles have been found.
* ''inputstyle:'' and ''liststyle:''<br>are CSS declarations that modify the default input and listbox styles, respectively. Note: the CSS styles must be surrounded by ({{{"..."}}} or {{{'...'}}}) or ({{{[[...]]}}}) (e.g., {{{liststyle:"border:1px dotted blue;color:green;..."}}}.
* ''filter:''<br>is a single tag value (or a boolean tag expression if MatchTagsPlugin is installed), and is used to limit the search to only those tiddlers matching the indicated tag or tag expression (e.g., {{{<<gotoTiddler filter:"faq or help">>}}})
{{{<<gotoTiddler>>}}}
<<gotoTiddler>>
{{{<<gotoTiddler search>>}}}
<<gotoTiddler search>>
{{{<<gotoTiddler showlist filter:"pluginInfo" liststyle:"height:10em;width:auto;">>}}}
<<gotoTiddler showlist filter:"pluginInfo" liststyle:"height:10em;width:auto;">>
<<<
!!!!!Configuration
<<<
*Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input. //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
*To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
//{{{
config.macros.gotoTiddler.listMaxSize=10; // change this number
//}}}
<<<
!!!!!Revisions
<<<
2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
2009.04.12 [1.9.1] support multiple instances with different filters by using per-element tiddler cache instead of shared static cache
2009.04.05 [1.9.0] added 'showlist' parameter for inline display with listbox always visible.
2009.03.23 [1.8.0] added txtIncrementalSearchMin (default=3). Avoids fetching long lists. Use down arrow to force search with short input.
2008.12.15 [1.7.1] up arrow from input field now moves to end of droplist (search for input). Also, shift+enter cam now be used to quickly invoke search for text.
2008.10.16 [1.7.0] in macro handler(), changed to use //named// params instead of positional params, and added optional "filter:" param for tag filtering. Removed 'insert' handling (now provided by [[QuickEditPlugin]]).
2008.10.02 [1.6.1] for IE, wrap controls in a table. Corrects placement of listbox so it is below input field.
2008.10.02 [1.6.0] added 'search' param for optional "Search for:" item that invokes full text search (especially useful when no title matches are found)
2008.02.17 [1.5.0] ENTER key always displays tiddler based on current input regardless of whether input matches any existing tiddler
2007.10.31 [1.4.3] removed extra trailing comma on last property of config.macros.gotoTiddler object. This fixes an error under InternetExplorer that was introduced 6 days ago... sure, I should have found it sooner, but... WHY DON'T PEOPLE TELL ME WHEN THINGS ARE BROKEN!!!!
2007.10.25 [1.4.2] added onclick handler for input field, so that clicking in field hides the listbox.
2007.10.25 [1.4.1] re-wrote getItems() to cache list of tiddlers/shadows/tags and use case-folded simple text match instead of regular expression to find matching tiddlers. This *vastly* reduces processing overhead between keystrokes, especially for documents with many (>1000) tiddlers. Also, removed local definition of replaceSelection(), now supported directly by the TW2.2+ core, as well as via backward-compatible plugin
2007.04.25 [1.4.0] renamed macro from "goto" to "gotoTiddler". This was necessary to avoid a fatal syntax error in Opera (and other browsers) that require strict adherence to ECMAScript 1.5 standards which defines the identifier "goto" as "reserved for FUTURE USE"... *sigh*
2007.04.21 [1.3.2] in html definition, removed DIV around droplist (see 1.2.6 below). It created more layout problems then it solved. :-(
2007.04.01 [1.3.1] in processItem(), ensure that correct textarea field is found by checking for edit=="text" attribute
2007.03.30 [1.3.0] tweak SideBarOptions shadow to automatically add {{{<<goto>>}}} when using default sidebar content
2007.03.30 [1.2.6] in html definition, added DIV around droplist to fix IE problem where list appears next to input field instead of below it.
2007.03.28 [1.2.5] in processItem(), set focus to text area before setting selection (needed for IE to get correct selection 'range')
2007.03.28 [1.2.4] added prompt for 'pretty text' when inserting a link into tiddler content
2007.03.28 [1.2.3] added local copy of core replaceSelection() and modified for different replace logic
2007.03.27 [1.2.2] in processItem(), use story.getTiddlerField() to retrieve textarea control
2007.03.26 [1.2.1] in html, use either 'onkeydown' (IE) or 'onkeypress' (Moz) event to process <esc> key sooner, to prevent <esc> from 'bubbling up' to the tiddler (which will close the current editor).
2007.03.26 [1.2.0] added support for optional "insert" keyword param.
2006.05.10 [1.1.2] when filling listbox, set selection to 'heading' item... auto-select first tiddler title when down/enter moves focus into listbox
2006.05.08 [1.1.1] added accesskey ("G") to input field html (also set when field gets focus). Also, inputKeyHandler() skips non-printing/non-editing keys.
2006.05.08 [1.1.0] added heading to listbox for better feedback (also avoids problems with 1-line droplist)
2006.05.07 [1.0.0] list matches against tiddlers/shadows/tags. input field auto-completion... 1st enter=complete matching input (or show list)... 2nd enter=view tiddler. "quiet" param controls when listbox appears. handling for enter (13), escape(27), and down(40) keys. Change 'ondblclick' to 'onclick' to avoid unintended triggering of tiddler editor). Shadow titles inserted into list instead of appended to the end.
2006.05.05 [0.0.0] started
<<<
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|embed wiki syntax formatting inside of HTML content|
The ~HTMLFormatting plugin allows you to ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2009.01.05 [2.4.0] in wikifyTextNodes(), pass w.highlightRegExp and w.tiddler to wikify() so that search term highlighting and tiddler-relative macro processing will work
| see [[HTMLFormattingPluginInfo]] for additional revision details |
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormattingPlugin= {major: 2, minor: 4, revision: 0, date: new Date(2009,1,5)};
// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
if (i<config.formatters.length) config.formatters[i].handler=function(w) {
if (!this.lookaheadRegExp) // fixup for TW2.0.x
this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var html=lookaheadMatch[1];
// if <nowiki> is present, just let browser handle it!
if (html.indexOf('<nowiki>')!=-1)
createTiddlyElement(w.output,"span").innerHTML=html;
else {
// if <hide linebreaks> is present, suppress wiki-style literal handling of newlines
if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
// remove all \r's added by IE textarea and mask newlines and macro brackets
html=html.replace(/\r/g,'').replace(/\n/g,'\\n').replace(/<</g,'%%(').replace(/>>/g,')%%');
// create span, let browser parse HTML
var e=createTiddlyElement(w.output,"span"); e.innerHTML=html;
// then re-render text nodes as wiki-formatted content
wikifyTextNodes(e,w);
}
w.nextMatch = this.lookaheadRegExp.lastIndex; // continue parsing
}
}
}
// wikify #text nodes that remain after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode,w)
{
function unmask(s) { return s.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n'); }
switch (theNode.nodeName.toLowerCase()) {
case 'style': case 'option': case 'select':
theNode.innerHTML=unmask(theNode.innerHTML);
break;
case 'textarea':
theNode.value=unmask(theNode.value);
break;
case '#text':
var txt=unmask(theNode.nodeValue);
var newNode=createTiddlyElement(null,"span");
theNode.parentNode.replaceChild(newNode,theNode);
wikify(txt,newNode,highlightHack,w.tiddler);
break;
default:
for (var i=0;i<theNode.childNodes.length;i++)
wikifyTextNodes(theNode.childNodes.item(i),w); // recursion
break;
}
}
//}}}
|Name|HTMLFormattingPluginInfo|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for HTMLFormattingPlugin|
The ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Usage
<<<
The shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.
When a tiddler is about to be displayed, ~TiddlyWiki looks for tiddler content contained within {{{<html>}}} and {{{</html>}}} markers. When present, the TiddlyWiki core simply passes this content directly to the browser's internal "rendering engine" to process as ~HTML-formatted content. However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain. This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.
This plugin extends the TiddlyWiki core processing so that, after the HTML formatting has been processed, all the pieces of text occuring within the HTML block are then processed one piece at a time, so that normal wiki-style formatting can be applied to the individual text pieces.
Note: To bypass this extended processing for a specific section of HTML content, embed ''{{{<nowiki>}}}'' //anywhere// inside the {{{<html>...</html>}}} delimiters, and wiki formatting will not be applied to that content.
<<<
!!!!!Line breaks
<<<
One major difference between Wiki formatting and HTML formatting is how "line breaks" are processed. Wiki formatting treats all line breaks as literal content to be displayed //as-is//. However, because HTML normally ignores line breaks and actually processes them as simple "word separators" instead, many people who write HTML include extra line breaks in their documents, just to make the "source code" easier to read.
Even though you can use HTML tags within your tiddler content, the default treatment for line breaks still follows the Wiki-style rule (i.e., all new lines are displayed as-is). When adding HTML content to a tiddler (especially if you cut-and-paste it from another web page), you should take care to avoid adding extra line breaks to the text.
If removing all the extra line breaks from your HTML content would be a big hassle, you can quickly //override the default Wiki-style line break rule// so that the line breaks use the standard HTML rules, by placing ''{{{<hide linebreaks>}}}'' //anywhere// within the HTML content. This automatically converts all line breaks to spaces before rendering the content, so that the literal line breaks will be processed as simple word-breaks instead.
Note: this does //not// alter the actual tiddler content that is stored in the document, just the manner in which it is displayed. Any line breaks contained in the tiddler will still be there when you edit its content. Also, to include a literal line break when the ''<{{{hide linebreaks}}}>'' tag is present, you will need to use a ''<{{{br}}}>'' or ''<{{{p}}}>'' HTML tag instead of simply typing a line break.
<<<
!!!!!How it works
<<<
The TW core support for HTML does not let you put ANY wiki-style syntax (including TW macros) *inside* the {{{<html>...</html>}}} block. Everything between {{{<html>}}} and {{{</html>}}} is handed to the browser for processing and that is it.
However, not all wiki syntax can be safely passed through the browser's parser. Specifically, any TW macros inside the HTML will get 'eaten' by the browser since the macro brackets, {{{<<...>>}}} use the "<" and ">" that normally delimit the HTML/XML syntax recognized by the browser's parser.
Similarly, you can't use InlineJavascript within the HTML because the {{{<script>...</script>}}} syntax will also be consumed by the browser and there will be nothing left to process afterward. Note: unfortunately, even though the browser removes the {{{<script>...</script>}}} sequence, it doesn't actually execute the embedded javascript code that it removes, so any scripts contained inside of <html> blocks in TW are currently being ignored. :-(
As a work-around to allow TW *macros* (but not inline scripts) to exist inside of <html> formatted blocks of content, the plugin first converts the {{{<<}}} and {{{>>}}} into "%%(" and ")%%", making them "indigestible" so they can pass unchanged through the belly of the beast (the browser's HTML parser).
After the browser has done its job, the wiki syntax sequences (including the "undigested" macros) are contained in #text nodes in the browser-generated DOM elements. The plugin then recursively locates and processes each #text node, converts the %%( and )%% back into {{{<<}}} and {{{>>}}}, passes the result to wikify() for further rendering of the wiki-formatted syntax into a containing SPAN that replaces the previous #text node. At the end of this process, none of the encoded %%( and )%% sequences remain in the rendered tiddler output.
<<<
!!!!!Revisions
<<<
2009.01.05 2.4.0 in wikifyTextNodes(), pass w.highlightRegExp and w.tiddler to wikify() so that search term highlighting and tiddler-relative macro processing will work
2008.10.02 2.3.0 added use of {{{<nowiki>}}} marker to bypass all wikification inside a specific HTML block
2008.09.19 2.2.0 in wikifyTextNodes(), don't wikify the contents of STYLE nodes (thanks to MorrisGray for bug report)
2008.04.26 [*.*.*] plugin size reduction: more documentation moved to HTMLFormattingInfo
2008.01.08 [*.*.*] plugin size reduction: documentation moved to HTMLFormattingInfo
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.14 2.1.5 in formatter, removed call to e.normalize(). Creates an INFINITE RECURSION error in Safari!!!!
2006.09.10 2.1.4 update formatter for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)
2006.05.28 2.1.3 in wikifyTextNodes(), decode the *value* of TEXTAREA nodes, but don't wikify() its children. (thanks to "ayj" for bug report)
2006.02.19 2.1.2 in wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content. This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)
2006.02.05 2.1.1 wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.01 2.1.0 don't wikify #TEXT nodes inside SELECT and TEXTAREA elements
2005.11.06 2.0.1 code cleanup
2005.10.31 2.0.0 replaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code
2005.10.09 1.0.2 combined documentation and code into a single tiddler
2005.08.05 1.0.1 moved HTML and CSS definitions into plugin code instead of using separate tiddlers
2005.07.26 1.0.1 Re-released as a plugin. Added <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling
2005.06.26 1.0.0 Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.hideWhenLastTest = false;
window.removeElementWhen = function(test,place) {
window.hideWhenLastTest = test;
if (test) {
removeChildren(place);
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}},
hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title == params[0], place);
}},
showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title != params[0], place);
}},
'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !window.hideWhenLastTest, place);
}}
});
//}}}
http://www.example.com/class/images/
/***
|Name|ImagePathPlugin|
|Source|http://www.TiddlyTools.com/#ImagePathPlugin|
|Version|0.7.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|Tell TiddlyWiki where to look for image files. Permits multiple 'fallback' locations|
|Status|ALPHA - initial development/testing only - may be unstable - do not distribute|
!!!!!Usage
<<<
This plugin adds "resolvePath()" fallback processing to the {{{[img[...]]}}} formatter's handler, so that local image file references can be successfully resolved, even if the files cannot be located on the local filesystem.
The plugin tries alternative file "paths" that are listed, one per line, in an optional tiddler, [[ImagePathList]]. Each path in the list is combined with the image filename, which is then checked for existence, until the file is located. If no alternative is found, or [[ImagePathList]] is not present, then a 'last-ditch' fallback is attempted using the remote system and path specified in [[SiteUrl]] (if present).
If no fallback attempt is successful (i.e., because no [[ImagePathList]] OR [[SiteUrl]] tiddlers have been defined), the plugin simply passes the original image file value along for default handling by the browser without any "path resolution" being applied.(i.e, the current TW core behavior occurs).
| ''Important note: This plugin may cause one or more security alert messages to appear, because it uses browser-specific functions that can require security permission in order to access the local filesystem to check for the existence of a given image file. If you block local access, the 'last-ditch' fallback using the remote [[SiteUrl]] (if present) will be attempted.'' |
Note: the image formatter code contained here also includes support for AttachFilePlugin extensions (if installed). AttachFilePlugin includes its own fallback mechanism for handling embedded vs. local file vs. remote URL references to the attached binary file. Both methods may be used: ImagePathPlugin provides fallback for images contained in tiddler content, while AttachFilePlugin works well for access to non-image binary files (or images used in CSS as backgrounds, textures, etc.)
<<<
!!!!!Examples
<<<
coming soon...
<<<
!!!!!Revisions
<<<
''2007.04.13 [0.7.1]'' in testFile(), convert any file:// references to local native format before checking for existence.
''2007.03.26 [0.7.0]'' for IE, use onError handling to trigger call to resolvePath() so it will only be invoked if the original path/file is not found by the browser-native lookup. This avoids an unneeded call to fileExists() and the accompanying ActiveX security alert message box (as well as being slightly more efficient...)
''2007.03.25 [0.6.0]'' code cleanup (moved global functions into config.formatterHelpers) plus documentation re-write
''2007.03.24 [0.5.0]'' initial implementation - ALPHA - do not distribute
<<<
!!!!!Code
***/
//{{{
version.extensions.ImagePathPlugin= {major: 0, minor: 7, revision: 1, date: new Date(2007,4,13)};
//}}}
//{{{
// name of path definition tiddler
if (config.options.txtPathTiddler==undefined) config.options.txtPathTiddler="ImagePathList";
//}}}
//{{{
// low-level wrapper for platform-specific tests for local file existence
// returns true/false without visible error display
// Uses Components for FF and ActiveX FSO object for MSIE
// NOTE: this can cause a security warning on some browsers
config.formatterHelpers.fileExists=function(theFile) {
var found=false;
// DEBUG: alert('testing fileExists('+theFile+')...');
if(window.Components) {
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
catch(e) { return false; } // security access denied
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
try { file.initWithPath(theFile); }
catch(e) { return false; } // invalid directory
found = file.exists();
}
else { // use ActiveX FSO object for MSIE
var fso = new ActiveXObject("Scripting.FileSystemObject");
found = fso.FileExists(theFile)
}
// DEBUG: alert(theFile+" "+(found?"exists":"not found"));
return found;
}
//}}}
//{{{
// higher-level logic for checking local file existence.
// with secondary check for finding relative file references
// and automatic OK of http-based references without checking local filesystem
config.formatterHelpers.testFile=function(theFile) {
if (document.location.protocol!="file:") return true; // viewing remote document, can't test local filesystem... assume OK
if (theFile.substr(0,5)=="http:") return true; // remote HTTP reference... assume OK
if (theFile.substr(0,5)=="file:") theFile=getLocalPath(theFile); // convert local FILE reference to native format
if (this.fileExists(theFile)) return true; // file exists locally... OK to use!
// file might have been relative, add path from current document and try again
var docPath=document.location.href;
var slashpos=docPath.lastIndexOf("/"); if (slashpos==-1) slashpos=docPath.lastIndexOf("\\");
if (slashpos!=-1 && slashpos!=docPath.length-1) docPath=docPath.substr(0,slashpos+1); // trim off filename
if (this.fileExists(getLocalPath(docPath+theFile)))
return true; // ah ha!... file exists relative to current document... OK to use!
return false; // file not found on local system
}
//}}}
//{{{
// given a path/file string, check for existence and
// try alternatives (if any) defined in a tiddler
// with last-ditch using system/path from SiteUrl (if any)
config.formatterHelpers.resolvePath=function(theFile,testoriginal) {
if (testoriginal && this.testFile(theFile)) return theFile; // FOUND FILE - use specified path/file without modification
// get the filename portion only
var slashpos=theFile.lastIndexOf("/"); if (slashpos==-1) slashpos=theFile.lastIndexOf("\\");
var theName=(slashpos==-1)?theFile:theFile.substr(slashpos+1);
// get list of fallbacks (if any)
var pathText=store.getTiddlerText(config.options.txtPathTiddler);
if (pathText && pathText.length) {
var paths=pathText.split("\n");
for (p=0; p<paths.length; p++) // combine path+filename until one works...
if (this.testFile(paths[p]+theName))
return paths[p]+theName; // FOUND FILE - use alternative path+filename
}
// try "last ditch" fallback using SiteURL - assumes that original path/file was relative to document location
var siteURL=store.getTiddlerText("SiteUrl");
if (!siteURL||!siteURL.length) return theFile; // NO FALLBACK - use original path/file and hope for the best
// trim filename (if any) from site URL
var slashpos=siteURL.lastIndexOf("/"); if (slashpos==-1) slashpos=siteURL.lastIndexOf("\\");
if (slashpos!=-1 && slashpos!=siteURL.length-1) siteURL=siteURL.substr(0,slashpos+1);
return siteURL+theFile; // LAST DITCH: use system/path from SiteUrl combined with original file/path
}
//}}}
//{{{
// replace standard handler for image formatter
// adds call to resolvePath() to handle fallback processing
// includes support for AttachFilePlugin as well
config.formatters[config.formatters.findByField("name","image")].handler=function(w) {
if (!this.lookaheadRegExp) // fixup for TW2.0.x
this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
// Simple bracketted link
var e = w.output;
if(lookaheadMatch[5]) {
var link = lookaheadMatch[5];
if (!config.formatterHelpers.isExternalLink) // fixup for TW2.0.x
var external=!store.tiddlerExists(link)&&!store.isShadowTiddler(link);
else
var external=config.formatterHelpers.isExternalLink(link);
if (external) {
if (config.macros.attach && config.macros.attach.isAttachment(link)) { // ELS - attachments
e = createExternalLink(w.output,link);
e.href=config.macros.attach.getAttachment(link);
e.title = config.macros.attach.linkTooltip + link;
} else
e = createExternalLink(w.output,link);
} else
e = createTiddlyLink(w.output,link,false,null,w.isStatic);
addClass(e,"imageLink");
}
var img = createTiddlyElement(e,"img");
if(lookaheadMatch[1])
img.align = "left";
else if(lookaheadMatch[2])
img.align = "right";
if(lookaheadMatch[3])
img.title = lookaheadMatch[3];
if (config.macros.attach!=undefined && config.macros.attach.isAttachment(lookaheadMatch[4])) // ELS - attachments
img.src=config.macros.attach.getAttachment(lookaheadMatch[4]);
else {
if (config.browser.isIE || config.browser.isSafari) { // ELS - path processing
// IE and Safari use browser's onError handling to check the original file...
// avoids extra security alert messages due to use of Components/ActiveX for filesystem access
img.onerror=(function(){this.src=config.formatterHelpers.resolvePath(this.src,false);return false;});
img.src=lookaheadMatch[4]; // ELS - path processing
} else {
// if NOT IE or Safari, always check the original path/file before rendering
img.src=config.formatterHelpers.resolvePath(lookaheadMatch[4],true);
}
}
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
//}}}
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.2.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|adds support for resizing images|
This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
!!!!!Usage
<<<
The extended image syntax is:
{{{
[img(w+,h+)[...][...]]
}}}
where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between """{{""" and """}}""". Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
<<<
!!!!!Examples
<<<
{{{
[img(100px+,75px+)[images/meow2.jpg]]
}}}
[img(100px+,75px+)[images/meow2.jpg]]
{{{
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img( 1%+,+)[images/meow.gif]]
}}}
[<img(34%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img( 1%+,+)[images/meow.gif]]
{{tagClear{
}}}
<<<
!!!!!Revisions
<<<
2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
2009.02.22 [1.2.0] added stretchable images
2008.01.19 [1.1.0] added evaluated width/height values
2008.01.18 [1.0.1] regexp for "(width,height)" now passes all CSS values to browser for validation
2008.01.17 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 1, date: new Date(2009,2,24)};
//}}}
//{{{
var f=config.formatters[config.formatters.findByField("name","image")];
f.match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
f.lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](?:\(([^,]*),([^\)]*)\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
f.handler=function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var floatLeft=lookaheadMatch[1];
var floatRight=lookaheadMatch[2];
var width=lookaheadMatch[3];
var height=lookaheadMatch[4];
var tooltip=lookaheadMatch[5];
var src=lookaheadMatch[6];
var link=lookaheadMatch[7];
// Simple bracketted link
var e = w.output;
if(link) { // LINKED IMAGE
if (config.formatterHelpers.isExternalLink(link)) {
if (config.macros.attach && config.macros.attach.isAttachment(link)) {
// see [[AttachFilePluginFormatters]]
e = createExternalLink(w.output,link);
e.href=config.macros.attach.getAttachment(link);
e.title = config.macros.attach.linkTooltip + link;
} else
e = createExternalLink(w.output,link);
} else
e = createTiddlyLink(w.output,link,false,null,w.isStatic);
addClass(e,"imageLink");
}
var img = createTiddlyElement(e,"img");
if(floatLeft) img.align="left"; else if(floatRight) img.align="right";
if(width||height) {
var x=width.trim(); var y=height.trim();
var stretchW=(x.substr(x.length-1,1)=='+'); if (stretchW) x=x.substr(0,x.length-1);
var stretchH=(y.substr(y.length-1,1)=='+'); if (stretchH) y=y.substr(0,y.length-1);
if (x.substr(0,2)=="{{")
{ try{x=eval(x.substr(2,x.length-4))} catch(e){displayMessage(e.description||e.toString())} }
if (y.substr(0,2)=="{{")
{ try{y=eval(y.substr(2,y.length-4))} catch(e){displayMessage(e.description||e.toString())} }
img.style.width=x.trim(); img.style.height=y.trim();
config.formatterHelpers.addStretchHandlers(img,stretchW,stretchH);
}
if(tooltip) img.title = tooltip;
// GET IMAGE SOURCE
if (config.macros.attach && config.macros.attach.isAttachment(src))
src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
if (config.browser.isIE || config.browser.isSafari) {
img.onerror=(function(){
this.src=config.formatterHelpers.resolvePath(this.src,false);
return false;
});
} else
src=config.formatterHelpers.resolvePath(src,true);
}
img.src=src;
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
e.title=((stretchW||stretchH)?'DRAG=stretch/shrink, ':'')
+'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size';
e.statusMsg='width=%0, height=%1';
e.style.cursor='move';
e.originalW=e.style.width;
e.originalH=e.style.height;
e.minW=Math.max(e.offsetWidth/20,10);
e.minH=Math.max(e.offsetHeight/20,10);
e.stretchW=stretchW;
e.stretchH=stretchH;
e.onmousedown=function(ev) { var ev=ev||window.event;
this.sizing=true;
this.startX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
this.startY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
this.startW=this.offsetWidth;
this.startH=this.offsetHeight;
return false;
};
e.onmousemove=function(ev) { var ev=ev||window.event;
if (this.sizing) {
var s=this.style;
var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
}
return false;
};
e.onmouseup=function(ev) { var ev=ev||window.event;
if (ev.shiftKey) { this.style.width=this.style.height=''; }
if (ev.ctrlKey) { this.style.width=this.originalW; this.style.height=this.originalH; }
this.sizing=false;
clearMessage();
return false;
};
e.onmouseout=function(ev) { var ev=ev||window.event;
this.sizing=false;
clearMessage();
return false;
};
}
//}}}
The plugins in this package provide interactive functionality for importing/exporting tiddlers to/from other TiddlyWiki documents. Additional plugins provide enhanced local/remote file I/O features, including "save as", "save from web" and "upload" functionality.
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|interactive controls for import/export with filtering.|
Combine tiddlers from any two TiddlyWiki documents. Interactively select and copy tiddlers from another TiddlyWiki source document. Includes prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. When done, a list of all imported tiddlers is written into [[ImportedTiddlers]].
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Revisions
<<<
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImportTiddlersPlugin= {major: 4, minor: 6, revision: 0, date: new Date(2009,10,6)};
// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;
// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;
// default shadow definition
config.shadowTiddlers.ImportTiddlers='<<importTiddlers inline>>';
// use shadow tiddler content in backstage panel
if (config.tasks) config.tasks.importTask.content='<<tiddler ImportTiddlers>>' // TW2.2 or above
//}}}
//{{{
// backward-compatiblity for TW2.0.x and TW1.2.x
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={};
if (typeof merge=='undefined') {
function merge(dst,src,preserveExisting) {
for(var i in src) { if(!preserveExisting || dst[i] === undefined) dst[i] = src[i]; }
return dst;
}
}
if (config.browser.isGecko===undefined)
config.browser.isGecko=(config.userAgent.indexOf('gecko')!=-1);
//}}}
//{{{
merge(config.macros.importTiddlers,{
$: function(id) { return document.getElementById(id); }, // abbreviation
label: 'import tiddlers',
prompt: 'Copy tiddlers from another document',
openMsg: 'Opening %0',
openErrMsg: 'Could not open %0 - error=%1',
readMsg: 'Read %0 bytes from %1',
foundMsg: 'Found %0 tiddlers in %1',
filterMsg: "Filtered %0 tiddlers matching '%1'",
summaryMsg: '%0 tiddler%1 in the list',
summaryFilteredMsg: '%0 of %1 tiddler%2 in the list',
plural: 's are',
single: ' is',
countMsg: '%0 tiddlers selected for import',
processedMsg: 'Processed %0 tiddlers',
importedMsg: 'Imported %0 of %1 tiddlers from %2',
loadText: 'please load a document...',
closeText: 'close',
doneText: 'done',
startText: 'import',
stopText: 'stop',
local: true, // default to import from local file
src: '', // path/filename or URL of document to import (retrieved from SiteUrl)
proxy: '', // URL for remote proxy script (retrieved from SiteProxy)
useProxy: false, // use specific proxy script in front of remote URL
inbound: null, // hash-indexed array of tiddlers from other document
newTags: '', // text of tags added to imported tiddlers
addTags: true, // add new tags to imported tiddlers
listsize: 10, // # of lines to show in imported tiddler list
importTags: true, // include tags from remote source document when importing a tiddler
keepTags: true, // retain existing tags when replacing a tiddler
sync: false, // add 'server' fields to imported tiddlers (for sync function)
lastFilter: '', // most recent filter (URL hash) applied
lastAction: null, // most recent collision button performed
index: 0, // current processing index in import list
sort: '' // sort order for imported tiddler listbox
});
//}}}
//{{{
// hijack core macro handler
if (config.macros.importTiddlers.coreHandler==undefined)
config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler;
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
if (config.macros.importTiddlers.coreHandler)
config.macros.importTiddlers.coreHandler.apply(this,arguments);
else
createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
} else if (params[0]=='link') { // show link to floating panel
createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
} else if (params[0]=='inline') {// show panel as INLINE tiddler content
createImportPanel(place);
this.$('importPanel').style.position='static';
this.$('importPanel').style.display='block';
} else if (config.macros.loadTiddlers)
config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
//{{{
// Handle link click to create/show/hide control panel
function onClickImportMenu(e) { var e=e||window.event;
var parent=resolveTarget(e).parentNode;
var panel=document.getElementById('importPanel');
if (panel==undefined || panel.parentNode!=parent) panel=createImportPanel(parent);
var isOpen=panel.style.display=='block';
if(config.options.chkAnimate)
anim.startAnimating(new Slider(panel,!isOpen,false,'none'));
else
panel.style.display=isOpen?'none':'block';
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); return(false);
}
//}}}
//{{{
// Create control panel: HTML, CSS
function createImportPanel(place) {
var cmi=config.macros.importTiddlers; // abbrev
var panel=cmi.$('importPanel');
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(store.getTiddlerText('ImportTiddlersPlugin##css'),'importTiddlers');
panel=createTiddlyElement(place,'span','importPanel',null,null)
panel.innerHTML=store.getTiddlerText('ImportTiddlersPlugin##html');
refreshImportList();
if (!cmi.src.length) cmi.src=store.getTiddlerText('SiteUrl')||'';
cmi.$('importSourceURL').value=cmi.src;
if (!cmi.proxy.length) cmi.proxy=store.getTiddlerText('SiteProxy')||'SiteProxy';
cmi.$('importSiteProxy').value=cmi.proxy;
if (config.browser.isGecko) { // FF3 FIXUP
cmi.$('fileImportSource').style.display='none';
cmi.$('importLocalPanelFix').style.display='block';
}
cmi.$('chkSync').checked=cmi.sync;
cmi.$('chkImportTags').checked=cmi.importTags;
cmi.$('chkKeepTags').checked=cmi.keepTags;
cmi.$('chkAddTags').checked=cmi.addTags;
cmi.$('txtNewTags').value=cmi.newTags;
cmi.$('txtNewTags').style.display=cmi.addTags?'block':'none';
cmi.$('chkSync').checked=cmi.sync;
cmi.$('chkImportReport').checked=config.options.chkImportReport;
return panel;
}
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event) {
var cmi=config.macros.importTiddlers; // abbreviation
var list=cmi.$('importList'); if (!list) return false;
var thePanel=cmi.$('importPanel');
var theCollisionPanel=cmi.$('importCollisionPanel');
var theNewTitle=cmi.$('importNewTitle');
var count=0;
switch (which.id)
{
case 'importFromFile': // show local panel
case 'importFromWeb': // show HTTP panel
cmi.local=(which.id=='importFromFile');
cmi.showPanel('importLocalPanel',cmi.local);
cmi.showPanel('importHTTPPanel',!cmi.local);
break;
case 'importOptions': // show/hide options panel
cmi.showPanel('importOptionsPanel',cmi.$('importOptionsPanel').style.display=='none');
break;
case 'fileImportSource':
case 'importLoad': // load import source into hidden frame
importReport(); // if an import was in progress, generate a report
cmi.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
if (cmi.src=='') break;
// Load document, read it's DOM and fill the list
cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
break;
case 'importSelectFeed': // select a pre-defined systemServer feed URL
var p=Popup.create(which); if (!p) return false;
var tids=store.getTaggedTiddlers('systemServer');
if (!tids.length)
createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
for (var t=0; t<tids.length; t++) {
var u=store.getTiddlerSlice(tids[t].title,'URL');
var d=store.getTiddlerSlice(tids[t].title,'Description');
if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,'description');
if (!d||!d.length) d=u;
createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
function(){
var u=this.getAttribute('url');
document.getElementById('importSourceURL').value=u;
config.macros.importTiddlers.src=u;
document.getElementById('importLoad').onclick();
},
null,null,null,{url:u});
}
Popup.show();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
// create popup with feed list
// onselect, insert feed URL into input field.
break;
case 'importSelectAll': // select all tiddler list items (i.e., not headings)
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < list.options.length; t++) {
if (list.options[t].value=='') continue;
list.options[t].selected=true;
count++;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!count;
break;
case 'importSelectNew': // select tiddlers not in current document
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value=='') continue;
list.options[t].selected=!store.tiddlerExists(list.options[t].value);
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!count;
break;
case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value==''||!store.tiddlerExists(list.options[t].value)) continue;
for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!count;
break;
case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < list.options.length; t++) {
list.options[t].selected=false;
if (list.options[t].value=='') continue;
if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
count+=list.options[t].selected?1:0;
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
cmi.$('importStart').disabled=!count;
break;
case 'importApplyFilter': // filter list to include only matching tiddlers
importReport(); // if an import was in progress, generate a report
clearMessage();
if (!cmi.all) // no tiddlers loaded = '0 selected'
{ displayMessage(cmi.countMsg.format([0])); return false; }
var hash=cmi.$('importLastFilter').value;
cmi.inbound=cmi.filterByHash('#'+hash,cmi.all);
refreshImportList(); // reset/resize the listbox
break;
case 'importStart': // initiate the import processing
importReport(); // if an import was in progress, generate a report
cmi.$('importApplyToAll').checked=false;
cmi.$('importStart').value=cmi.stopText;
if (cmi.index>0) cmi.index=-1; // stop processing
else cmi.index=importTiddlers(0); // or begin processing
importStopped();
break;
case 'importClose': // unload imported tiddlers or hide the import control panel
// if imported tiddlers not loaded, close the import control panel
if (!cmi.inbound) { thePanel.style.display='none'; break; }
importReport(); // if an import was in progress, generate a report
cmi.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
break;
case 'importSkip': // don't import the tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
theImported.status='skipped after asking'; // mark item as skipped
theCollisionPanel.style.display='none';
cmi.index=importTiddlers(cmi.index+1); // resume with NEXT item
importStopped();
break;
case 'importRename': // change name of imported tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
theImported.status = 'renamed from '+theImported.title; // mark item as renamed
theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title
theItem.value = theNewTitle.value; // change the listbox item text
theItem.text = theNewTitle.value; // change the listbox item text
theCollisionPanel.style.display='none';
cmi.index=importTiddlers(cmi.index); // resume with THIS item
importStopped();
break;
case 'importMerge': // join existing and imported tiddler content
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
var theExisting = store.getTiddler(theItem.value);
var theText = theExisting.text+'\n----\n^^merged from: ';
theText +='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
var theDate = new Date();
var theTags = theExisting.getTags()+' '+theImported.getTags();
theImported.set(null,theText,null,theDate,theTags);
theImported.status = 'merged with '+theExisting.title; // mark item as merged
theImported.status += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
cmi.index=importTiddlers(cmi.index); // resume with this item
importStopped();
break;
case 'importReplace': // substitute imported tiddler for existing tiddler
cmi.lastAction=which;
var theItem = list.options[cmi.index];
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==theItem.value) break;
var theImported = cmi.inbound[j];
var theExisting = store.getTiddler(theItem.value);
theImported.status = 'replaces '+theExisting.title; // mark item for replace
theImported.status += ' - '+theExisting.modified.formatString('MM/DD/YYYY 0hh:0mm:0ss');
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
cmi.index=importTiddlers(cmi.index); // resume with THIS item
importStopped();
break;
case 'importListSmaller': // decrease current listbox size, minimum=5
if (list.options.length==1) break;
list.size-=(list.size>5)?1:0;
cmi.listsize=list.size;
break;
case 'importListLarger': // increase current listbox size, maximum=number of items in list
if (list.options.length==1) break;
list.size+=(list.size<list.options.length)?1:0;
cmi.listsize=list.size;
break;
case 'importListMaximize': // toggle listbox size between current and maximum
if (list.options.length==1) break;
list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
break;
}
}
//}}}
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
if (typeof place=='string') var place=document.getElementById(place);
if (!place||!place.style) return;
if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,'none'));
else place.style.display=show?'block':'none';
}
//}}}
//{{{
function refreshImportList(selectedIndex) {
var cmi=config.macros.importTiddlers; // abbrev
var list=cmi.$('importList'); if (!list) return;
// if nothing to show, reset list content and size
if (!cmi.inbound) {
while (list.length > 0) { list.options[0] = null; }
list.options[0]=new Option(cmi.loadText,'',false,false);
list.size=cmi.listsize;
cmi.$('importLoad').disabled=false;
cmi.$('importLoad').style.display='inline';
cmi.$('importStart').disabled=true;
cmi.$('importOptions').disabled=true;
cmi.$('importOptions').style.display='none';
cmi.$('fileImportSource').disabled=false;
cmi.$('importFromFile').disabled=false;
cmi.$('importFromWeb').disabled=false;
cmi.$('importStart').value=cmi.startText;
cmi.$('importClose').value=cmi.doneText;
cmi.$('importSelectPanel').style.display='none';
cmi.$('importOptionsPanel').style.display='none';
return;
}
// there are inbound tiddlers loaded...
cmi.$('importLoad').disabled=true;
cmi.$('importLoad').style.display='none';
cmi.$('importOptions').style.display='inline';
cmi.$('importOptions').disabled=false;
cmi.$('fileImportSource').disabled=true;
cmi.$('importFromFile').disabled=true;
cmi.$('importFromWeb').disabled=true;
cmi.$('importClose').value=cmi.closeText;
if (cmi.$('importSelectPanel').style.display=='none')
cmi.showPanel('importSelectPanel',true);
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) cmi.sort='title'; // heading
if (selectedIndex==1) cmi.sort='title';
if (selectedIndex==2) cmi.sort='modified';
if (selectedIndex==3) cmi.sort='tags';
if (selectedIndex>3) {
// display selected tiddler count
for (var t=0,count=0; t < list.options.length; t++) {
if (!list.options[t].selected) continue;
if (list.options[t].value!='')
count+=1;
else { // if heading is selected, deselect it, and then select and count all in section
list.options[t].selected=false;
for ( t++; t<list.options.length && list.options[t].value!=''; t++) {
list.options[t].selected=true;
count++;
}
}
}
clearMessage(); displayMessage(cmi.countMsg.format([count]));
}
cmi.$('importStart').disabled=!count;
if (selectedIndex>3) return; // no refresh needed
// get the alphasorted list of tiddlers
var tiddlers=cmi.inbound;
tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
// clear current list contents
while (list.length > 0) { list.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
if (cmi.all.length==tiddlers.length)
var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
else
var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
list.options[i++]=new Option(summary,'',false,false);
list.options[i++]=new Option(((cmi.sort=='title' )?'>':indent)+' [by title]','',false,false);
list.options[i++]=new Option(((cmi.sort=='modified')?'>':indent)+' [by date]','',false,false);
list.options[i++]=new Option(((cmi.sort=='tags')?'>':indent)+' [by tags]','',false,false);
// output the tiddler list
switch(cmi.sort) {
case 'title':
for(var t = 0; t < tiddlers.length; t++)
list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
break;
case 'modified':
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
var lastSection = '';
for(var t = 0; t < tiddlers.length; t++) {
var tiddler = tiddlers[t];
var theSection = tiddler.modified.toLocaleDateString();
if (theSection != lastSection) {
list.options[i++] = new Option(theSection,'',false,false);
lastSection = theSection;
}
list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
}
break;
case 'tags':
var theTitles = {}; // all tiddler titles, hash indexed by tag value
var theTags = new Array();
for(var t=0; t<tiddlers.length; t++) {
var title=tiddlers[t].title;
var tags=tiddlers[t].tags;
if (!tags || !tags.length) {
if (theTitles['untagged']==undefined) { theTags.push('untagged'); theTitles['untagged']=new Array(); }
theTitles['untagged'].push(title);
}
else for(var s=0; s<tags.length; s++) {
if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
theTitles[tags[s]].push(title);
}
}
theTags.sort();
for(var tagindex=0; tagindex<theTags.length; tagindex++) {
var theTag=theTags[tagindex];
list.options[i++]=new Option(theTag,'',false,false);
for(var t=0; t<theTitles[theTag].length; t++)
list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
list.selectedIndex=selectedIndex; // select current control item
if (list.size<cmi.listsize) list.size=cmi.listsize;
if (list.size>list.options.length) list.size=list.options.length;
}
//}}}
//{{{
// re-entrant processing for handling import with interactive collision prompting
function importTiddlers(startIndex) {
var cmi=config.macros.importTiddlers; // abbrev
if (!cmi.inbound) return -1;
var list=cmi.$('importList'); if (!list) return;
var t;
// if starting new import, reset import status flags
if (startIndex==0)
for (var t=0;t<cmi.inbound.length;t++)
cmi.inbound[t].status='';
for (var i=startIndex; i<list.options.length; i++) {
// if list item is not selected or is a heading (i.e., has no value), skip it
if ((!list.options[i].selected) || ((t=list.options[i].value)==''))
continue;
for (var j=0;j<cmi.inbound.length;j++)
if (cmi.inbound[j].title==t) break;
var inbound = cmi.inbound[j];
var theExisting = store.getTiddler(inbound.title);
// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
if (inbound.status=='added')
continue;
// don't import the 'ImportedTiddlers' history from the other document...
if (inbound.title=='ImportedTiddlers')
continue;
// if tiddler exists and import not marked for replace or merge, stop importing
if (theExisting && (inbound.status.substr(0,7)!='replace') && (inbound.status.substr(0,5)!='merge'))
return i;
// assemble tags (remote + existing + added)
var newTags = '';
if (cmi.importTags)
newTags+=inbound.getTags() // import remote tags
if (cmi.keepTags && theExisting)
newTags+=' '+theExisting.getTags(); // keep existing tags
if (cmi.addTags && cmi.newTags.trim().length)
newTags+=' '+cmi.newTags; // add new tags
inbound.set(null,null,null,null,newTags.trim());
// set the status to 'added' (if not already set by the 'ask the user' UI)
inbound.status=(inbound.status=='')?'added':inbound.status;
// set sync fields
if (cmi.sync) {
if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
inbound.fields['server.page.revision']=inbound.modified.convertToYYYYMMDDHHMM();
inbound.fields['server.type']='file';
inbound.fields['server.host']=(cmi.local&&!cmi.src.startsWith('file:')?'file:///':'')+cmi.src;
}
// do the import!
store.suspendNotifications();
store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
store.resumeNotifications();
}
return(-1); // signals that we really finished the entire list
}
function importStopped() {
var cmi=config.macros.importTiddlers; // abbrev
var list=cmi.$('importList'); if (!list) return;
var theNewTitle=cmi.$('importNewTitle');
if (cmi.index==-1){
cmi.$('importStart').value=cmi.startText;
importReport(); // import finished... generate the report
} else {
// import collision...
// show the collision panel and set the title edit field
cmi.$('importStart').value=cmi.stopText;
cmi.showPanel('importCollisionPanel',true);
theNewTitle.value=list.options[cmi.index].value;
if (cmi.$('importApplyToAll').checked && cmi.lastAction && cmi.lastAction.id!='importRename')
onClickImportButton(cmi.lastAction);
}
}
//}}}
//{{{
function importReport() {
var cmi=config.macros.importTiddlers; // abbrev
if (!cmi.inbound) return;
// if import was not completed, the collision panel will still be open... close it now.
var panel=cmi.$('importCollisionPanel'); if (panel) panel.style.display='none';
// get the alphasorted list of tiddlers
var tiddlers = cmi.inbound;
// gather the statistics
var count=0; var total=0;
for (var t=0; t<tiddlers.length; t++) {
if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
if (tiddlers[t].status.substr(0,7)!='skipped') count++;
total++;
}
// generate a report
if (total) displayMessage(cmi.processedMsg.format([total]));
if (count && config.options.chkImportReport) {
// get/create the report tiddler
var theReport = store.getTiddler('ImportedTiddlers');
if (!theReport) { theReport=new Tiddler(); theReport.title='ImportedTiddlers'; theReport.text=''; }
// format the report content
var now = new Date();
var newText = 'On '+now.toLocaleString()+', '+config.options.txtUserName
newText +=' imported '+count+' tiddler'+(count==1?'':'s')+' from\n[['+cmi.src+'|'+cmi.src+']]:\n';
if (cmi.addTags && cmi.newTags.trim().length)
newText += 'imported tiddlers were tagged with: "'+cmi.newTags+'"\n';
newText += '<<<\n';
for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status)
newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
newText += '<<<\n';
// update the ImportedTiddlers content and show the tiddler
theReport.text = newText+((theReport.text!='')?'\n----\n':'')+theReport.text;
theReport.modifier = config.options.txtUserName;
theReport.modified = new Date();
store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
story.displayTiddler(null,theReport.title,1,null,null,false);
story.refreshTiddler(theReport.title,1,true);
}
// reset status flags
for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status='';
// mark document as dirty and let display update as needed
if (count) { store.setDirty(true); store.notifyAll(); }
// always show final message when tiddlers were actually loaded
if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g,' ')]));
}
//}}}
//{{{
// // File and XMLHttpRequest I/O
config.macros.importTiddlers.askForFilename=function(here) {
var msg=here.title; // use tooltip as dialog box message
var path=getLocalPath(document.location.href);
var slashpos=path.lastIndexOf('/'); if (slashpos==-1) slashpos=path.lastIndexOf('\\');
if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
var file='';
var result='';
if(window.Components) { // moz
try {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
picker.init(window, msg, nsIFilePicker.modeOpen);
var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
thispath.initWithPath(path);
picker.displayDirectory=thispath;
picker.defaultExtension='html';
picker.defaultString=file;
picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
}
catch(e) { alert('error during local file access: '+e.toString()) }
}
else { // IE
try { // XPSP2 IE only
var s = new ActiveXObject('UserAccounts.CommonDialog');
s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
s.FilterIndex=3; // default to HTML files;
s.InitialDir=path;
s.FileName=file;
if (s.showOpen()) var result=s.FileName;
}
catch(e) { // fallback
var result=prompt(msg,path+file);
}
}
return result;
}
config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
if (src==undefined || !src.length) return null; // filename is required
var original=src; // URL as specified
var hashpos=src.indexOf('#'); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
clearMessage();
displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
if (src.substr(0,5)!='http:' && src.substr(0,5)!='file:') { // if not a URL, read from local filesystem
var txt=loadFile(src);
if (!txt) { // file didn't load, might be relative path.. try fixup
var pathPrefix=document.location.href; // get current document path and trim off filename
var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\');
if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
src=pathPrefix+src;
if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
var txt=loadFile(src);
}
if (!txt) { // file still didn't load, report error
displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g,' '),'(filesystem error)']));
} else {
displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
if (version.major+version.minor*.1+version.revision*.01!=2.52) txt=convertUTF8ToUnicode(txt);
if (callback) callback(true,original,txt,src,null);
}
} else {
doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,original,null);
}
}
config.macros.importTiddlers.readTiddlersFromHTML=function(html){
var remoteStore=new TiddlyWiki();
remoteStore.importTiddlyWiki(html);
return remoteStore.getTiddlers('title');
}
config.macros.importTiddlers.readTiddlersFromCSV=function(CSV){
var remoteStore=new TiddlyWiki();
// GET NAMES
var lines=CSV.replace(/\r/g,'').split('\n');
var names=lines.shift().replace(/"/g,'').split(',');
CSV=lines.join('\n');
// ENCODE commas and newlines within quoted values
var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
CSV=CSV.replace(/"([^"]*?)"/g,
function(x){ return x.replace(/\,/g,comma).replace(/\n/g,newline); });
// PARSE lines
var lines=CSV.split('\n');
for (var i=0; i<lines.length; i++) { if (!lines[i].length) continue;
var values=lines[i].split(',');
// DECODE commas, newlines, and doubled-quotes, and remove enclosing quotes (if any)
for (var v=0; v<values.length; v++)
values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n')
.replace(/^"|"$/g,'').replace(/""/g,'"');
// EXTRACT tiddler values
var title=''; var text=''; var tags=[]; var fields={};
var created=null; var when=new Date(); var who=config.options.txtUserName;
for (var v=0; v<values.length; v++) { var val=values[v];
if (names[v]) switch(names[v].toLowerCase()) {
case 'title': title=val.replace(/\[\]\|/g,'_'); break;
case 'created': created=new Date(val); break;
case 'modified':when=new Date(val); break;
case 'modifier':who=val; break;
case 'text': text=val; break;
case 'tags': tags=val.readBracketedList(); break;
default: fields[names[v].toLowerCase()]=val; break;
}
}
// CREATE tiddler in temporary store
if (title.length)
remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
}
return remoteStore.getTiddlers('title');
}
config.macros.importTiddlers.createTiddlerFromFile=function(src,txt) {
var t=new Tiddler();
var pos=src.lastIndexOf("/"); if (pos==-1) pos=src.lastIndexOf("\\");
t.title=pos==-1?src:src.substr(pos+1);
t.text=txt;
t.created=t.modified=new Date();
t.modifier=config.options.txtUserName;
if (src.substr(src.length-3,3)=='.js') t.tags=['systemConfig'];
return [t];
}
config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr){
var cmi=config.macros.importTiddlers; // abbreviation
var src=src.replace(/%20/g,' ');
if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
cmi.all=cmi.readTiddlersFromHTML(txt);
if (!cmi.all||!cmi.all.length) cmi.all=cmi.readTiddlersFromCSV(txt)
if (!cmi.all||!cmi.all.length) cmi.all=cmi.createTiddlerFromFile(src,txt)
var count=cmi.all?cmi.all.length:0;
var querypos=src.lastIndexOf('?'); if (querypos!=-1) src=src.substr(0,querypos);
displayMessage(cmi.foundMsg.format([count,src]));
cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
cmi.$('importLastFilter').value=cmi.lastFilter;
window.refreshImportList(0);
}
config.macros.importTiddlers.filterByHash=function(src,tiddlers){
var hashpos=src.lastIndexOf('#'); if (hashpos==-1) return tiddlers;
var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
var tids=[];
var params=hash.parseParams('anon',null,true,false,false);
for (var p=1; p<params.length; p++) {
switch (params[p].name) {
case 'anon':
case 'open':
tids.pushUnique(params[p].value);
break;
case 'tag':
if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
} else for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].isTagged(params[p].value))
tids.pushUnique(tiddlers[t].title);
break;
case 'story':
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].title==params[p].value) {
tiddlers[t].changed();
for (var s=0; s<tiddlers[t].links.length; s++)
tids.pushUnique(tiddlers[t].links[s]);
break;
}
break;
case 'search':
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].text.indexOf(params[p].value)!=-1)
tids.pushUnique(tiddlers[t].title);
break;
}
}
var matches=[];
for (var t=0; t<tiddlers.length; t++)
if (tids.contains(tiddlers[t].title))
matches.push(tiddlers[t]);
displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
config.macros.importTiddlers.lastFilter=hash;
return matches;
}
//}}}
/***
!!!Control panel CSS
//{{{
!css
#importPanel {
display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;
background-color: #eee; color:#000; font-size: 8pt; line-height:110%;
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;
padding: 0.5em; margin:0em; -moz-border-radius:1em;-webkit-border-radius:1em;
}
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }
#importPanel select { width:100%;margin:0px;font-size:8pt;line-height:110%;}
#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;-webkit-border-radius:5px;}
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }
#importPanel .rad { width:auto; }
#importPanel .chk { width:auto; margin:1px;border:0; }
#importPanel .btn { width:auto; }
#importPanel .btn1 { width:98%; }
#importPanel .btn2 { width:48%; }
#importPanel .btn3 { width:32%; }
#importPanel .btn4 { width:23%; }
#importPanel .btn5 { width:19%; }
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }
#backstagePanel #importPanel { left:10%; right:auto; }
!end
//}}}
!!!Control panel HTML
//{{{
!html
<!-- source and report -->
<table><tr><td align=left>
import from
<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED
onclick="onClickImportButton(this,event)" title="show file controls"> local file
<input type="radio" class="rad" name="importFrom" id="importFromWeb" value="http"
onclick="onClickImportButton(this,event)" title="show web controls"> web server
</td><td align=right>
<input type=checkbox class="chk" id="chkImportReport"
onClick="config.options['chkImportReport']=this.checked;"> create report
</td></tr></table>
<div class="box" id="importSourcePanel" style="margin:.5em">
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file -->
enter or browse for source path/filename<br>
<input type="file" id="fileImportSource" size=57 style="width:100%"
onKeyUp="config.macros.importTiddlers.src=this.value"
onChange="config.macros.importTiddlers.src=this.value;document.getElementById('importLoad').onclick()">
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->
<input type="text" id="fileImportSourceFix" style="width:90%"
title="Enter a path/file to import"
onKeyUp="config.macros.importTiddlers.src=this.value"
onChange="config.macros.importTiddlers.src=this.value;document.getElementById('importLoad').onclick()">
<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."
title="Select a path/file to import"
onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;
document.getElementById('fileImportSourceFix').value=r;
config.macros.importTiddlers.src=r;
document.getElementById('importLoad').onclick()">
</div><!--end FF3 FIXUP-->
</div><!--end local-->
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->
<table><tr><td align=left>
enter a URL or <a href="javascript:;" id="importSelectFeed"
onclick="return onClickImportButton(this,event)" title="select a pre-defined 'systemServer' URL">
select a server</a><br>
</td><td align=right>
<input type="checkbox" class="chk" id="importUsePassword"
onClick="config.macros.importTiddlers.usePassword=this.checked;
config.macros.importTiddlers.showPanel('importIDPWPanel',this.checked,true);">password
<input type="checkbox" class="chk" id="importUseProxy"
onClick="config.macros.importTiddlers.useProxy=this.checked;
config.macros.importTiddlers.showPanel('importSiteProxy',this.checked,true);">proxy
</td></tr></table>
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"
onKeyUp="config.macros.importTiddlers.proxy=this.value"
onChange="config.macros.importTiddlers.proxy=this.value;">
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"
onKeyUp="config.macros.importTiddlers.src=this.value"
onChange="config.macros.importTiddlers.src=this.value;">
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>
username: <input type=text id="txtImportID" style="width:25%"
onChange="config.options.txtRemoteUsername=this.value;">
password: <input type=password id="txtImportPW" style="width:25%"
onChange="config.options.txtRemotePassword=this.value;">
</div><!--end idpw-->
</div><!--end http-->
</div><!--end source-->
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">
<table><tr><td align=left>
select:
<a href="javascript:;" id="importSelectAll"
onclick="return onClickImportButton(this)" title="SELECT all tiddlers">
all</a>
<a href="javascript:;" id="importSelectNew"
onclick="return onClickImportButton(this)" title="SELECT tiddlers not already in destination document">
added</a>
<a href="javascript:;" id="importSelectChanges"
onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been updated in source document">
changes</a>
<a href="javascript:;" id="importSelectDifferences"
onclick="return onClickImportButton(this)" title="SELECT tiddlers that have been added or are different from existing tiddlers">
differences</a>
</td><td align=right>
<a href="javascript:;" id="importListSmaller"
onclick="return onClickImportButton(this)" title="SHRINK list size">
– </a>
<a href="javascript:;" id="importListLarger"
onclick="return onClickImportButton(this)" title="GROW list size">
+ </a>
<a href="javascript:;" id="importListMaximize"
onclick="return onClickImportButton(this)" title="MAXIMIZE/RESTORE list size">
= </a>
</td></tr></table>
<select id="importList" size=8 multiple
onchange="setTimeout('refreshImportList('+this.selectedIndex+')',1)">
<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->
</select>
<div style="text-align:center">
<a href="javascript:;"
title="click for help using filters..."
onclick="alert('A filter consists of one or more space-separated combinations of: tiddlertitle, tag:[[tagvalue]], tag:[[tag expression]] (requires MatchTagsPlugin), story:[[TiddlerName]], and/or search:[[searchtext]]. Use a blank filter to restore the list of all tiddlers.'); return false;"
>filter</a>
<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"
title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."
onfocus="this.select()" value=""
onKeyUp="config.macros.importTiddlers.lastFilter=this.value"
onChange="config.macros.importTiddlers.lastFilter=this.value;">
<input type="button" id="importApplyFilter" style="width:20%" value="apply"
title="filter list of tiddlers to include only those that match certain criteria"
onclick="return onClickImportButton(this)">
</div>
</div><!--end select-->
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">
apply tags: <input type=checkbox class="chk" id="chkImportTags" checked
onClick="config.macros.importTiddlers.importTags=this.checked;">from source
<input type=checkbox class="chk" id="chkKeepTags" checked
onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing
<input type=checkbox class="chk" id="chkAddTags"
onClick="config.macros.importTiddlers.addTags=this.checked;
config.macros.importTiddlers.showPanel('txtNewTags',this.checked,false);
if (this.checked) document.getElementById('txtNewTags').focus();">add tags<br>
<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15 onfocus="this.select()"
title="enter tags to be added to imported tiddlers"
onKeyUp="config.macros.importTiddlers.newTags=this.value;
document.getElementById('chkAddTags').checked=this.value.length>0;" autocomplete=off>
<nobr><input type=checkbox class="chk" id="chkSync"
onClick="config.macros.importTiddlers.sync=this.checked;">
link tiddlers to source document (for sync later)</nobr>
</div><!--end options-->
<div id="importButtonPanel" style="text-align:center">
<input type=button id="importLoad" class="importButton btn3" value="open"
title="load listbox with tiddlers from source document"
onclick="onClickImportButton(this)">
<input type=button id="importOptions" class="importButton btn3" value="options..."
title="set options for tags, sync, etc."
onclick="onClickImportButton(this)">
<input type=button id="importStart" class="importButton btn3" value="import"
title="start/stop import of selected source tiddlers into current document"
onclick="onClickImportButton(this)">
<input type=button id="importClose" class="importButton btn3" value="done"
title="clear listbox or hide control panel"
onclick="onClickImportButton(this)">
</div>
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">
<table><tr><td style="width:65%" align="left">
<table><tr><td align=left>
tiddler already exists:
</td><td align=right>
<input type=checkbox class="chk" id="importApplyToAll"
onclick="document.getElementById('importRename').disabled=this.checked;"
checked>apply to all
</td></tr></table>
<input type=text id="importNewTitle" size=15 autocomplete=off">
</td><td style="width:34%" align="center">
<input type=button id="importMerge"
class="importButton" style="width:47%" value="merge"
title="append the incoming tiddler to the existing tiddler"
onclick="onClickImportButton(this)"><!--
--><input type=button id="importSkip"
class="importButton" style="width:47%" value="skip"
title="do not import this tiddler"
onclick="onClickImportButton(this)"><!--
--><br><input type=button id="importRename"
class="importButton" style="width:47%" value="rename"
title="rename the incoming tiddler"
onclick="onClickImportButton(this)"><!--
--><input type=button id="importReplace"
class="importButton" style="width:47%" value="replace"
title="discard the existing tiddler"
onclick="onClickImportButton(this)">
</td></tr></table>
</div><!--end collision-->
!end
//}}}
***/
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for ImportTiddlersPlugin|
Combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a source document and import selected tiddlers, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Usage
<<<
{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}
invokes the built-in importTiddlers macro (TW2.1.x+). If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)
{{{<<importTiddlers link label tooltip>>}}}
The ''link'' keyword creates an "import tiddlers" link that when clicked to show/hide import control panel. ''label'' and ''tooltip'' are optional text parameters (enclosed in quotes or {{{[[...]]}}}, and allow you to override the default display text for the link and the mouseover help text, respectively.
{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content
<<importTiddlers inline>>
Enter a document URL or press "..." to select a TiddlyWiki file to import, and then press ''[open]''. //Note: There may be a delay before the list of tiddlers appears.// Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time.
Select one or more titles from the listbox. Use CTRL-click or SHIFT-click to select/deselect individual titles. Click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list, based on a comparison of the two documents:
*''all'' selects ALL tiddlers from the import source document, even if they have not been changed.
*''new'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
*''changes'' selects only tiddlers that exist in both documents but that are newer in the source document
*''differences'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)
Press ''[import]'' to begin copying tiddlers to the current document. If an 'inbound' tiddler matches one that already exists in the document, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''skip'', ''rename'', ''merge'' and ''replace''.
* to bypass importing the tiddler, press ''skip''
* to give the inbound tiddler a different name, so that both the old and new tiddlers will exist when the import is done, enter a new title in the input field and press ''rename''
* to combine the content from both tiddlers into a single tiddler so you can then edit it later to eliminate unwanted content, press ''merge''
* to overwrite the existing tiddler with the imported one (discarding the previous content), press ''[replace]''
''Import Report History''
Whenever tiddlers are imported, a report is generated into a tiddler named [[ImportedTiddlers]], recording when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom, as well as a list of the tiddlers that were processed. When more tiddlers are imported at a later time, a new report is //added// to the existing [[ImportedTiddlers]], above the previous report (i.e., at the top of the tiddler), so that a history of imports is maintained. If this record is not desired, you can delete [[ImportedTiddlers]] at any time.
Note: You can prevent a report from being generated for any given import activity by clearing the "create a report" checkbox before pressing the ''import'' button
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, support for TW2.1.x and earlier have been moved to [[ImportTiddlersPluginPatch]]. ''//Only install the patch plugin when using TW2.1.x or earlier.//''
<<<
!!!!!Revisions
<<<
2009.10.06 4.6.0 added createTiddlerFromFile (import text files)
2009.09.27 4.5.5 in readTiddlersFromCSV(), strip \r from input and fixed handling for quoted values
2009.09.12 4.5.4 fixed 'return false' to prevent IE page transition. Also, moved html/css definitions to separate sections
2009.08.23 4.5.3 in importTiddlers(), add 'file:///' to local server.host sync field only if not already present in URL
2009.08.20 4.5.2 only use SiteURL/SiteProxy values if control panel value has not yet been set
2009.07.03 4.5.1 fixups for TW252: doHttp() doesn't return XHR and convertUTF8ToUnicode() not needed for local I/O
2009.05.04 4.5.0 import from CSV-formatted files
2009.03.04 4.4.2 in createImportPanel(), init option checkboxes so display matches internal state variables
2009.02.26 4.4.1 use macro-specific definition of $() function abbreviation (avoids conflict with JQuery)
2008.09.30 4.4.0 added fallback definition of merge() for use with TW2.0.x and TW1.2.x
2008.08.12 4.3.3 rewrite backstage and shadow tiddler definitions for easier customization
2008.08.05 4.3.2 rewrote loadRemoteFile() to eliminate use of platform-specific fileExists() function
2008.06.29 4.3.1 More layout/animation work for simpler sequential interaction. Code reduction/cleanup
2008.06.28 4.3.0 HTML and CSS cleanup and tweaks to layout. Added animation to panels
2008.06.22 4.2.0 For FireFox, use HTML with separate text+button control instead of type='file' control
2008.06.05 4.1.0 in filterByHash(), added support for boolean tag expressions using getMatchingTiddlers() (defined by MatchTagsPlugin)
2008.05.12 4.0.2 automatically tweak the backstage "import" task to add the ImportTiddlers control panel
2008.04.30 4.0.1 trim #... suffix for loading files/URLs in IE
2008.04.30 4.0.0 added source filtering (using URL paramifiers). Also, abbreviations for code-size reduction.
2008.04.13 3.9.0 added 'apply to all' checkbox for collision processing
2008.03.26 3.8.0 added support for selecting pre-defined systemServer URLs
2008.03.25 3.7.0 added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
2008.01.03 3.6.0 in loadRemoteFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.10.30 3.5.6 update [[ImportTiddlers]] shadow tiddler definition to include "inline" link
2007.06.27 3.5.5 added missing 'fields' params to saveTiddler() calls. Fixes problem where importing tiddlers would lose the custom fields. Also, moved functions for TW2.1.x to [[ImportTiddlersPluginPatch2.1.x]].
2007.06.25 3.5.4 added calls to store.suspendNotifications() and store.resumeNotifications(). Eliminates redisplay processing overhead DURING import activities
2007.04.29 3.5.3 in refreshImportList() when inbound tiddlers are loaded, change "close" button to "done", and disable certain controls to creates a modal condition, so that actions that reload tiddlers cannot be performed unless "done" is first pressed to end the mode..
2007.04.28 3.5.2 in handler(), added param support for custom link label/prompt
2007.04.19 3.5.1 in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content. Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.03.22 3.5.0 in refreshImportList(), add handling for 'select section' when a heading is selected. Makes it really easy to import by tag or date!
2007.03.21 3.4.0 split loadTiddlers functionality into separate plugin (see [[LoadTiddlersPlugin]])
2007.03.20 3.3.1 tweak to previous change to allow relative file references via http: (bypasses getLocalPath() so remote URL will be used)
2007.03.20 3.3.0 added support for local, relative file references: in loadRemoteFile(), check for fileExists(). If not found, prepend relative path and retry.
2007.02.24 3.2.1 re-labeled control panel "open" button to "load"
2007.02.09 3.2.0 loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)
2007.02.08 3.1.3 loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)
2006.11.14 3.1.2 fix macro handler parameter declaration (double-pasted param list corrupts IE)
2006.11.13 3.1.1 use apply() method to invoke hijacked core handler
2006.11.13 3.1.0 hijack built-in importTiddlers.handler() to co-exist with plugin interface. If no params or 'core' keyword, display core interface. "link" param embeds "import tiddlers" link that shows floating panel when clicked.
2006.10.12 3.0.8 in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)
2006.09.10 3.0.7 in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body"
2006.08.16 3.0.6 Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with adaptations that hijack low-level tiddler handling. in CreateImportPanel(), removed "refresh listbox after every tiddler change".
2006.07.29 3.0.5 added noChangeMsg to loadTiddlers processing. if not 'quiet' mode, reports skipped tiddlers.
2006.04.18 3.0.4 in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)
2006.04.12 3.0.3 moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.
2006.04.12 3.0.2 more work on 'core candidate' code. Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.
2006.04.04 3.0.1 in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section
2006.04.04 3.0.0 Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Removed support for "importReplace/importPublic" tags and "force" param (unused feature).
2006.03.30 2.9.1 when extracting store area from remote URL, look for "</body>" instead of "</body>\n</html>" so it will match even if the "\n" is absent from the source.
2006.03.30 2.9.0 added optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.
2006.03.28 2.8.1 in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (not in IE). Also, when extracting store area, look for "</body>\n</html>" and omit extra content that may have been added to the end of the file.
2006.02.21 2.8.0 added support for "tiddler:TiddlerName" filtering parameter in auto-import processing
2006.02.21 2.7.1 Clean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)
2006.02.21 2.7.0 Added "local file" and "web server" radio buttons. Default remote URL uses value from [[SiteURL]]. Also, added 'proxy' option, using value from [[SiteProxy]] as prefix to permit cross-domain document access via server-side scripting.
2006.02.17 2.6.0 Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. fixed init of "add new tags" checkbox
2006.02.16 2.5.4 added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.
2006.02.14 2.5.3 FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()
2006.02.10 2.5.2 corrected unintended global variable in importReport().
2006.02.05 2.5.1 moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals
2006.01.18 2.5.0 added checkbox for "create a report". Default is to create/update the ImportedTiddlers report.
2006.01.15 2.4.1 added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic
2006.01.15 2.4.0 Added support for tagging tiddlers with importSkip, importReplace, and/or importPrivate to enable/disable overwriting or sharing with others when using auto-import macro syntax. Defaults: don't overwrite existing tiddlers, and allow your tiddlers to be auto-imported by others.
2006.01.15 2.3.2 Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)
2006.01.15 2.3.1 Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME to prevent imported document's core code from being invoked. Also, when importing local documents, use convertUTF8ToUnicode() to support international characters sets.
2006.01.12 2.3.0 Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest instead of waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' mode, using macro parameters to specify source path/file or URL, and select tiddlers to import. Improved messages and added optional 'quiet' switch for batch mode to eliminate //most// feedback.
2006.01.11 2.2.0 Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
2006.01.08 2.1.0 IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.
2006.01.06 2.0.2 When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.
2006.01.04 2.0.1 When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.
2005.12.27 2.0.0 Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
2005.12.22 1.3.1 tweak formatting in importReport() and add 'discard report' link to output
2005.12.03 1.3.0 Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)
2005.11.29 1.2.1 fixed formatting of 'detail info' in importReport()
2005.11.11 1.2.0 added 'inline' param to embed controls in a tiddler
2005.11.09 1.1.0 only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.
2005.10.25 1.0.5 fixed typo in importReport() that prevented reports from being generated
2005.10.09 1.0.4 combined documentation with plugin code instead of using separate tiddlers
2005.08.05 1.0.3 moved CSS and HTML definitions into plugin code instead of using separate tiddlers
2005.07.27 1.0.2 core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()
2005.07.23 1.0.1 added parameter checks and corrected addNotification() usage
2005.07.20 1.0.0 Initial Release
<<<
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.5|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // external script library
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // inline code
if (show) // display source in tiddler
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create 'onclick' command link
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run script immediately
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name|InlineJavascriptPluginInfo|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for InlineJavascriptPlugin|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Usage
<<<
This plugin adds wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be recognized as embedded javascript code.
<script show>
/* javascript code goes here... */
</script>Every time the tiddler content is rendered, the javascript code is automatically evaluated, allowing you to invoke 'side-effect' processing and/or produce dynamically-generated content that is then inserted into the tiddler content, immediately following the script (see below). By including the optional ''show'' keyword as the final parameter in a {{{<script>}}} marker, the plugin will also include the script source code in the output that it displays in the tiddler. This is helpful when creating examples for documentation purposes (such as used in this tiddler!)
__''Deferred execution from an 'onClick' link''__
<script label="click here" title="mouseover tooltip text" key="X" show>
/* javascript code goes here... */
alert('you clicked on the link!');
</script>
By including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered. You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text, and a {{{key="X"}}} parameter to specify an //access key// (which must be a //single// letter or numeric digit only).
__''Loading scripts from external source files''__
<script src="URL" show>
/* optional javascript code goes here... */
</script>You can also load javascript directly from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.
In addition to loading the javascript from the external file, you can also use this feature to invoke javascript code contained within the {{{<script>...</script>}}} markers. This code is invoked //after// the external script file has been processed, and can make immediate use of the functions and/or global variables defined by the external script file.
>Note: To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that is rendered as soon as your TiddlyWiki document is opened, such as MainMenu. For example: put your {{{<script src="..."></script>}}} syntax into a separate 'library' tiddler (e.g., LoadScripts), and then add {{{<<tiddler LoadScripts>>}}} to MainMenu so that the library is loaded before any other tiddlers that rely upon the functions it defines.
>
>Normally, loading external javascript in this way does not produce any direct output, and should not have any impact on the appearance of your MainMenu. However, if your LoadScripts tiddler contains notes or other visible content, you can suppress this output by using 'inline CSS' in the MainMenu, like this: {{{@@display:none;<<tiddler LoadScripts>>@@}}}
<<<
!!!!!Creating dynamic tiddler content and accessing the ~TiddlyWiki DOM
<<<
An important difference between TiddlyWiki inline scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document: in a typical web document, you use the {{{document.write()}}} (or {{{document.writeln()}}}) function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.
However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and instead will //completely replace the entire ~TiddlyWiki document in your browser window (which is clearly not a good thing!)//. In order to allow scripts to use {{{document.write()}}}, the plugin automatically converts and buffers all HTML output so it can be safely inserted into your tiddler content, immediately following the script.
''Note that {{{document.write()}}} can only be used to output "pure HTML" syntax. To produce //wiki-formatted// output, your script should instead return a text value containing the desired wiki-syntax content'', which will then be automatically rendered immediately following the script. If returning a text value is not sufficient for your needs, the plugin also provides an automatically-defined variable, 'place', that gives the script code ''direct access to the //containing DOM element//'' into which the tiddler output is being rendered. You can use this variable to ''perform direct DOM manipulations'' that can, for example:
* generate wiki-formatted output using {{{wikify("...content...",place)}}}
* vary the script's actions based upon the DOM element in which it is embedded
* access 'tiddler-relative' DOM information using {{{story.findContainingTiddler(place)}}}
Note:
''When using an 'onclick' script, the 'place' element actually refers to the onclick //link text// itself, instead of the containing DOM element.'' This permits you to directly reference or modify the link text to reflect any 'stateful' conditions that might set by the script. To refer to the containing DOM element from within an 'onclick' script, you can use "place.parentNode" instead.
<<<
!!!!!Instant "bookmarklets"
<<<
You can also use an 'onclick' link to define a "bookmarklet": a small piece of javascript that can be ''invoked directly from the browser without having to be defined within the current document.'' This allows you to create 'stand-alone' commands that can be applied to virtually ANY TiddlyWiki document... even remotely-hosted documents that have been written by others!! To create a bookmarklet, simply define an 'onclick' script and then grab the resulting link text and drag-and-drop it onto your browser's toolbar (or right-click and use the 'bookmark this link' command to add it to the browser's menu).
Notes:
*When writing scripts intended for use as bookmarklets, due to the ~URI-encoding required by the browser, ''you cannot not use ANY double-quotes (") within the bookmarklet script code.''
*All comments embedded in the bookmarklet script must ''use the fully-delimited {{{/* ... */}}} comment syntax,'' rather than the shorter {{{//}}} comment syntax.
*Most importantly, because bookmarklets are invoked directly from the browser interface and are not embedded within the TiddlyWiki document, there is NO containing 'place' DOM element surrounding the script. As a result, ''you cannot use a bookmarklet to generate dynamic output in your document,'' and using {{{document.write()}}} or returning wiki-syntax text or making reference to the 'place' DOM element will halt the script and report a "Reference Error" when that bookmarklet is invoked.
Please see [[InstantBookmarklets]] for many examples of 'onclick' scripts that can also be used as bookmarklets.
<<<
!!!!!Special reserved function name
<<<
The plugin 'wraps' all inline javascript code inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.
<<<
!!!!!$(...) 'shorthand' function
<<<
As described by Dustin Diaz [[here|http://www.dustindiaz.com/top-ten-javascript/]], the plugin defines a 'shorthand' function that allows you to write:
{{{
$(id)
}}}
in place of the normal standard javascript syntax:
{{{
document.getElementById(id)
}}}
This function is provided merely as a convenience for javascript coders that may be familiar with this abbreviation, in order to allow them to save a few bytes when writing their own inline script code.
<<<
!!!!!Examples
<<<
simple dynamic output:
><script show>
document.write("The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
if (!window.story) window.story=window;
var title=story.findContainingTiddler(place).getAttribute("tiddler");
var size=store.getTiddlerText(title).length;
return title+" is using "+size+" bytes";
</script>
dynamic output from an 'onclick' script, using {{{document.write()}}} and/or {{{return "..."}}}
><script label="click here" show>
document.write("<br>The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
creating an 'onclick' button/link that accesses the link text AND the containing tiddler:
><script label="click here" title="clicking this link will show an 'alert' box" key="H" show>
if (!window.story) window.story=window;
var txt=place.firstChild.data;
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
alert('Hello World!\nlinktext='+txt+'\ntiddler='+tid);
</script>
dynamically setting onclick link text based on stateful information:
>{{block{
{{{
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.previousSibling.innerHTML=on?"disable":"enable";
</script>
}}}
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.innerHTML=on?"enable":"disable";
</script>
}}}
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function inlineJavascriptDemo() { alert('Hello from demo.js!!') } }}}
>>{{{displayMessage('InlineJavascriptPlugin: demo.js has been loaded');}}}
>note: When using this example on your local system, you will need to download the external script file from the above URL and install it into the same directory as your document.
>
><script src="demo.js" show>
return "inlineJavascriptDemo() function has been defined"
</script>
><script label="click to invoke inlineJavascriptDemo()" key="D" show>
inlineJavascriptDemo();
</script>
<<<
!!!!!Revisions
<<<
2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
2008.06.11 [1.9.3] added $(...) function as 'shorthand' for document.getElementById()
2008.03.03 [1.9.2] corrected fallback declaration of wikifyPlainText() (fixes Safari "parse error")
2008.02.23 [1.9.1] in onclick function, use string instead of array for 'bufferedHTML' (fixes IE errors)
2008.02.21 [1.9.0] output from 'onclick' scripts (return value or document.write() calls) are now buffered and rendered into into a span following the script. Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed). Thanks to Xavier Verges for suggestion and preliminary code.
2008.02.14 [1.8.1] added backward-compatibility for use of wikifyPlainText() in TW2.1.3 and earlier
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 [1.8.0] added support for key="X" syntax to specify custom access key definitions
2007.12.15 [1.7.0] autogenerate URI encoded HREF on links for onclick scripts. Drag links to browser toolbar to create bookmarklets. IMPORTANT NOTE: place is NOT defined when scripts are used as bookmarklets. In addition, double-quotes will cause syntax errors. Thanks to PaulReiber for debugging and brainstorming.
2007.11.26 [1.6.2] when converting "document.write()" function calls in inline code, allow whitespace between "write" and "(" so that "document.write ( foobar )" is properly converted.
2007.11.16 [1.6.1] when rendering "onclick scripts", pass label text through wikifyPlainText() to parse any embedded wiki-syntax to enable use of HTML entities or even TW macros to generate dynamic label text.
2007.02.19 [1.6.0] added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
2006.10.16 [1.5.2] add newline before closing '}' in 'function out_' wrapper. Fixes error caused when last line of script is a comment.
2006.06.01 [1.5.1] when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly
2006.04.19 [1.5.0] added 'show' parameter to force display of javascript source code in tiddler output
2006.01.05 [1.4.0] added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.
2005.12.13 [1.3.1] when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski
2005.11.09 [1.3.0] for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck
2005.11.08 [1.2.0] handle loading of javascript from an external URL via src="..." syntax
2005.11.08 [1.1.0] pass 'place' param into scripts to provide direct DOM access
2005.11.08 [1.0.0] initial release
<<<
/***
|''Name:''|IntelliTaggerPlugin|
|''Version:''|1.0.2 (2007-07-25)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|
|''~SourceCode:''|[[IntelliTaggerPlugin SourceCode]]|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Version History
* 1.0.2 (2007-07-25):
** Feature: "Return" key may be used to accept first tag suggestion (beside "Alt-1")
** Bugfix: Keyboard shortcuts (Alt+3 etc.) shifted
* 1.0.1 (2007-05-18): Improvement: Speedup when using TiddlyWikis with many tags
* 1.0.0 (2006-04-26): Initial release
***/
// /%
if(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:2,date:new Date(2007,6,25),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.createEllipsis=function(_2){var e=createTiddlyElement(_2,"span");e.innerHTML="…";};abego.isPopupOpen=function(_4){return _4&&_4.parentNode==document.body;};abego.openAsPopup=function(_5){if(_5.parentNode!=document.body){document.body.appendChild(_5);}};abego.closePopup=function(_6){if(abego.isPopupOpen(_6)){document.body.removeChild(_6);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_7,_8,_9){_7.style.left=_8+"px";_7.style.top=_9+"px";};abego.centerOnWindow=function(_a){if(_a.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _b=abego.getWindowRect();abego.moveElement(_a,_b.left+(_b.width-_a.offsetWidth)/2,_b.top+(_b.height-_a.offsetHeight)/2);};abego.isDescendantOrSelf=function(_c,e){while(e){if(_c==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_e){var _f={};for(var i=0;i<_e.length;i++){_f[_e[i]]=true;}return _f;};abego.filterStrings=function(_11,_12,_13){var _14=[];for(var i=0;i<_11.length&&(_13===undefined||_14.length<_13);i++){var s=_11[i];if(s.match(_12)){_14.push(s);}}return _14;};abego.arraysAreEqual=function(a,b){if(!a){return !b;}if(!b){return false;}var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_1b,_1c){if(!_1c){return;}var _1d=findPosX(_1c);var _1e=findPosY(_1c);var _1f=_1c.offsetHeight;var _20=_1d;var _21=_1e+_1f;var _22=findWindowWidth();if(_22<_1b.offsetWidth){_1b.style.width=(_22-100)+"px";}var _23=_1b.offsetWidth;if(_20+_23>_22){_20=_22-_23-30;}if(_20<0){_20=0;}_1b.style.left=_20+"px";_1b.style.top=_21+"px";_1b.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _27=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_27.push([s.toString().toLowerCase(),s]);}_27.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_27[i][1];}};abego.getTiddlerField=function(_2d,_2e,_2f){var _30=document.getElementById(_2d.idPrefix+_2e);var e=null;if(_30!=null){var _32=_30.getElementsByTagName("*");for(var t=0;t<_32.length;t++){var c=_32[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2f){e=c;}}}}return e;};abego.setRange=function(_35,_36,end){if(_35.setSelectionRange){_35.setSelectionRange(_36,end);var max=0+_35.scrollHeight;var len=_35.textLength;var top=max*_36/len,bot=max*end/len;_35.scrollTop=Math.min(top,(bot+top-_35.clientHeight)/2);}else{if(_35.createTextRange!=undefined){var _3b=_35.createTextRange();_3b.collapse();_3b.moveEnd("character",end);_3b.moveStart("character",_36);_3b.select();}else{_35.select();}}};abego.internal.TagManager=function(){var _3c=null;var _3d=function(){if(_3c){return;}_3c={};store.forEachTiddler(function(_3e,_3f){for(var i=0;i<_3f.tags.length;i++){var tag=_3f.tags[i];var _42=_3c[tag];if(!_42){_42=_3c[tag]={count:0,tiddlers:{}};}_42.tiddlers[_3f.title]=true;_42.count+=1;}});};var _43=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_44,_45,_46,_47,_48,_49){var _4a=this.fetchTiddler(_44);var _4b=_4a?_4a.tags:[];var _4c=(typeof _49=="string")?_49.readBracketedList():_49;_43.apply(this,arguments);if(!abego.arraysAreEqual(_4b,_4c)){abego.internal.getTagManager().reset();}};var _4d=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4e){var _4f=this.fetchTiddler(_4e);var _50=_4f&&_4f.tags.length>0;_4d.apply(this,arguments);if(_50){abego.internal.getTagManager().reset();}};this.reset=function(){_3c=null;};this.getTiddlersWithTag=function(tag){_3d();var _52=_3c[tag];return _52?_52.tiddlers:null;};this.getAllTags=function(_53){_3d();var _54=[];for(var i in _3c){_54.push(i);}for(i=0;_53&&i<_53.length;i++){_54.pushUnique(_53[i],true);}abego.sortIgnoreCase(_54);return _54;};this.getTagInfos=function(){_3d();var _56=[];for(var _57 in _3c){_56.push([_57,_3c[_57]]);}return _56;};var _58=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3d();var _5e=this.getTagInfos();_5e.sort(_58);return _5e;};this.getPartnerRankedTags=function(_5f){var _60={};for(var i=0;i<_5f.length;i++){var _62=this.getTiddlersWithTag(_5f[i]);for(var _63 in _62){var _64=store.getTiddler(_63);if(!(_64 instanceof Tiddler)){continue;}for(var j=0;j<_64.tags.length;j++){var tag=_64.tags[j];var c=_60[tag];_60[tag]=c?c+1:1;}}}var _68=abego.toSet(_5f);var _69=[];for(var n in _60){if(!_68[n]){_69.push(n);}}_69.sort(function(a,b){var d=_60[b]-_60[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _69;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6e=2;var _6f=1;var _70=30;var _71;var _72;var _73;var _74;var _75;var _76;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _77=function(){return _72;};var _78=function(tag){return _75[tag];};var _7a=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7d=function(_7e){var s=_7e.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _81=function(_82){var s=_82.value;var len=s.length;if(len>0&&s[len-1]!=" "){_82.value+=" ";}};var _85=function(tag,_87,_88){if(_7d(_87)){_87.value=_7a(_87.value);}story.setTiddlerTag(_88.title,tag,0);_81(_87);abego.IntelliTagger.assistTagging(_87,_88);};var _89=function(n){if(_76&&_76.length>n){return _76[n];}return (_74&&_74.length>n)?_74[n]:null;};var _8b=function(n,_8d,_8e){var _8f=_89(n);if(_8f){_85(_8f,_8d,_8e);}};var _90=function(_91){var pos=_91.value.lastIndexOf(" ");var _93=(pos>=0)?_91.value.substr(++pos,_91.value.length):_91.value;return new RegExp(_93.escapeRegExp(),"i");};var _94=function(_95,_96){var _97=0;for(var i=0;i<_95.length;i++){if(_96[_95[i]]){_97++;}}return _97;};var _99=function(_9a,_9b,_9c){var _9d=1;var c=_9a[_9b];for(var i=_9b+1;i<_9a.length;i++){if(_9a[i][1].count==c){if(_9a[i][0].match(_9c)){_9d++;}}else{break;}}return _9d;};var _a0=function(_a1,_a2){var _a3=abego.internal.getTagManager().getSortedTagInfos();var _a4=[];var _a5=0;for(var i=0;i<_a3.length;i++){var c=_a3[i][1].count;if(c!=_a5){if(_a2&&(_a4.length+_99(_a3,i,_a1)>_a2)){break;}_a5=c;}if(c==1){break;}var s=_a3[i][0];if(s.match(_a1)){_a4.push(s);}}return _a4;};var _a9=function(_aa,_ab){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_ab),_aa);};var _ac=function(){if(!_71){return;}var _ad=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ad){_ad="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_71.innerHTML=_ad;applyHtmlMacros(_71,null);refreshElements(_71,null);};var _ae=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_73){_73.call(this,tag,e);}return false;};var _b2=function(_b3){createTiddlyElement(_b3,"span",null,"tagSeparator"," | ");};var _b4=function(_b5,_b6,_b7,_b8,_b9){if(!_b6){return;}var _ba=_b8?abego.toSet(_b8):{};var n=_b6.length;var c=0;for(var i=0;i<n;i++){var tag=_b6[i];if(_ba[tag]){continue;}if(c>0){_b2(_b5);}if(_b9&&c>=_b9){abego.createEllipsis(_b5);break;}c++;var _bf="";var _c0=_b5;if(_b7<10){_c0=createTiddlyElement(_b5,"span",null,"numberedSuggestion");_b7++;var key=_b7<10?""+(_b7):"0";createTiddlyElement(_c0,"span",null,"suggestionNumber",key+") ");var _c2=_b7==1?"Return or ":"";_bf=" (Shortcut: %1Alt-%0)".format([key,_c2]);}var _c3=config.views.wikified.tag.tooltip.format([tag]);var _c4=(_78(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_bf]);var _c5="%0; Shift-Click: %1".format([_c4,_c3]);var btn=createTiddlyButton(_c0,tag,_c5,_ae,_78(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c7=function(){if(_71){window.scrollTo(0,ensureVisible(_71));}if(_77()){window.scrollTo(0,ensureVisible(_77()));}};var _c8=function(e){if(!e){var e=window.event;}if(!_71){return;}var _cb=resolveTarget(e);if(_cb==_77()){return;}if(abego.isDescendantOrSelf(_71,_cb)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c8);var _cc=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_ce){_cc.apply(this,arguments);var _cf=_ce.tags;if(_cf){_ce.tags=_cf.trim();}};var _d0=function(_d1){story.focusTiddler(_d1,"tags");var _d2=abego.getTiddlerField(story,_d1,"tags");if(_d2){var len=_d2.value.length;abego.setRange(_d2,len,len);window.scrollTo(0,ensureVisible(_d2));}};var _d4=config.macros.edit.handler;config.macros.edit.handler=function(_d5,_d6,_d7,_d8,_d9,_da){_d4.apply(this,arguments);var _db=_d7[0];if((_da instanceof Tiddler)&&_db=="tags"){var _dc=_d5.lastChild;_dc.onfocus=function(e){abego.IntelliTagger.assistTagging(_dc,_da);setTimeout(function(){_d0(_da.title);},100);};_dc.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_8b(e.keyCode==48?9:e.keyCode-49,_dc,_da);}else{if(e.ctrlKey&&e.keyCode==32){_8b(0,_dc,_da);}}if(!e.ctrlKey&&(e.keyCode==13||e.keyCode==10)){_8b(0,_dc,_da);}setTimeout(function(){abego.IntelliTagger.assistTagging(_dc,_da);},100);return false;};_81(_dc);}};var _e0=function(e){if(!e){var e=window.event;}var _e3=resolveTarget(e);var _e4=_e3.getAttribute("tiddler");if(_e4){story.displayTiddler(_e3,_e4,"IntelliTaggerEditTagsTemplate",false);_d0(_e4);}return false;};var _e5=config.macros.tags.handler;config.macros.tags.handler=function(_e6,_e7,_e8,_e9,_ea,_eb){_e5.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_eb,createTiddlyElement(_e6.lastChild,"li"));};var _ec=function(){if(_71&&_72&&!abego.isDescendantOrSelf(document,_72)){abego.IntelliTagger.close();}};setInterval(_ec,100);abego.IntelliTagger.displayTagSuggestions=function(_ed,_ee,_ef,_f0,_f1){_74=_ed;_75=abego.toSet(_ee);_76=_ef;_72=_f0;_73=_f1;if(!_71){_71=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_71.style.position="absolute";}_ac();abego.openAsPopup(_71);if(_77()){var w=_77().offsetWidth;if(_71.offsetWidth<w){_71.style.width=(w-2*(_6e+_6f))+"px";}abego.moveBelowAndClip(_71,_77());}else{abego.centerOnWindow(_71);}_c7();};abego.IntelliTagger.assistTagging=function(_f3,_f4){var _f5=_90(_f3);var s=_f3.value;if(_7d(_f3)){s=_7a(s);}var _f7=s.readBracketedList();var _f8=_f7.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_f7),_f5,_70):_a0(_f5,_70);abego.IntelliTagger.displayTagSuggestions(_a9(_f5,_f7),_f7,_f8,_f3,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_85(tag,_f3,_f4);}});};abego.IntelliTagger.close=function(){abego.closePopup(_71);_71=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_fb,_fc,_fd,_fe,_ff,id,_101){if(!_fd){_fd="[edit]";}if(!_fe){_fe="Edit the tags";}if(!_ff){_ff="editTags";}var _102=createTiddlyButton(_fc,_fd,_fe,_e0,_ff,id,_101);_102.setAttribute("tiddler",(_fb instanceof Tiddler)?_fb.title:String(_fb));return _102;};abego.IntelliTagger.getSuggestionTagsMaxCount=function(){return 100;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_103,_104,_105,_106,_107,_108){var _109=_107.parseParams("list",null,true);var _10a=_109[0]["action"];for(var i=0;_10a&&i<_10a.length;i++){var _10c=_10a[i];var _10d=config.macros.intelliTagger.subhandlers[_10c];if(!_10d){abego.alertAndThrow("Unsupported action '%0'".format([_10c]));}_10d(_103,_104,_105,_106,_107,_108);}},subhandlers:{showTags:function(_10e,_10f,_110,_111,_112,_113){_b4(_10e,_74,_76?_76.length:0,_76,abego.IntelliTagger.getSuggestionTagsMaxCount());},showFavorites:function(_114,_115,_116,_117,_118,_119){_b4(_114,_76,0);},closeButton:function(_11a,_11b,_11c,_11d,_11e,_11f){var _120=createTiddlyButton(_11a,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_121){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_121,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_124){var e=createTiddlyElement(_124,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">© 2006-2007 <b><font color=\"red\">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\n"+"!~IntelliTagger Stylesheet\n"+"***/\n"+"/*{{{*/\n"+".intelliTaggerSuggestions {\n"+"\tposition: absolute;\n"+"\twidth: 600px;\n"+"\n"+"\tpadding: 2px;\n"+"\tlist-style: none;\n"+"\tmargin: 0;\n"+"\n"+"\tbackground: #eeeeee;\n"+"\tborder: 1px solid DarkGray;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .currentTag {\n"+"\tfont-weight: bold;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .suggestionNumber {\n"+"\tcolor: #808080;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .numberedSuggestion{\n"+"\twhite-space: nowrap;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter {\n"+"\tmargin-top: 4px;\n"+"\tborder-top-width: thin;\n"+"\tborder-top-style: solid;\n"+"\tborder-top-color: #999999;\n"+"}\n"+".intelliTaggerSuggestions .favorites {\n"+"\tborder-bottom-width: thin;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-color: #999999;\n"+"\tpadding-bottom: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .normalTags {\n"+"\tpadding-top: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\n"+"\tfont-size: 10px;\n"+"\n"+"\tpadding-left: 0.3em;\n"+"\tpadding-right: 0.3em;\n"+"}\n"+"\n"+"/*}}}*/\n";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class=\"favorites\" macro=\"intelliTagger action: showFavorites\"></div>\n"+"<div class=\"normalTags\" macro=\"intelliTagger action: showTags\"></div>\n"+"<!-- The Footer (with the Navigation) ============================================ -->\n"+"<table class=\"intelliTaggerFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n"+" <tr>\n"+"\t<td align=\"left\">\n"+"\t\t<span macro=\"intelliTagger action: closeButton\"></span>\n"+"\t</td>\n"+"\t<td align=\"right\">\n"+"\t\t<span macro=\"intelliTagger action: version\"></span>, <span macro=\"intelliTagger action: copyright \"></span>\n"+"\t</td>\n"+" </tr>\n"+"</tbody></table>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='title' macro='view title'></div>\n"+"<div class='tagged' macro='tags'></div>\n"+"<div class='viewer' macro='view text wikified'></div>\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/archive/IntelliTaggerPlugin/Plugin-IntelliTagger-src.1.0.2.js]]\n";(function(){var _126=restart;restart=function(){setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"IntelliTaggerStyleSheet");_126.apply(this,arguments);};})();}
// %/
/***
|''Name:''|IntelliTagsEditCommandPlugin|
|''Version:''|1.0.0 (2007-10-03)|
|''Type:''|plugin|
|''Description:''|A command for your tiddler's toolbar to directly edit the tiddler's tags using the IntelliTaggerPlugin, without switching to "edit mode".|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTagsEditCommandPlugin|
|''Requires:''|IntelliTaggerPlugin http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Using the "IntelliTagsEditCommandPlugin"
Add the command {{{intelliTagsEdit}}} into the 'macro' attribute of the 'toolbar' {{{<div...>}}} in your ViewTemplate.
''Example:''
{{{
<div class='toolbar'
macro='toolbar -closeTiddler closeOthers +editTiddler intelliTagsEdit permalink references jump'>
</div>
}}}
This adds a "tags" button to the toolbar of the tiddlers (next to the ''edit'' button). Pressing the "tags" button will open the input field for the tiddler's tags and let you edit the tags with all the [[IntelliTaggerPlugin|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin]] features.
***/
/***
!Source Code
***/
//{{{
(function(){
if (!version.extensions.IntelliTaggerPlugin)
throw Error("IntelliTagsEditCommandPlugin requires the IntelliTaggerPlugin (http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin)");
if (config.commands.intelliTagsEdit)
return;
config.commands.intelliTagsEdit = {
text: "tags",
tooltip: "edit the tags"
};
config.commands.intelliTagsEdit.handler = function(event,src,title) {
var button = abego.IntelliTagger.createEditTagsButton(title, null, "tags", "edit the tags");
button.onclick(event);
return false;
};
})();
//}}}
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.8.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
!!!!!Documentation
>see [[LoadTiddlersPluginInfo]]
!!!!!Configuration
<<<
<<option chkLoadTiddlersShowReport>>after loading tiddlers, automatically display [[ImportedTiddlers]] (if created)
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2009.10.08 3.8.1 removed switchTheme() from doImport()... causes an INFINITE cycle of imports!
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.LoadTiddlersPlugin= {major: 3, minor: 8, revision: 1, date: new Date(2009,10,8)};
if (config.options.chkLoadTiddlersShowReport===undefined)
config.options.chkLoadTiddlersShowReport=true;
config.macros.loadTiddlers = {
label: '',
tip: "add/update tiddlers from '%0'",
lockedTag: 'noReload', // if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
askMsg: 'Please enter a local path/filename or a remote URL',
openMsg: 'Opening %0',
openErrMsg: 'Could not open %0 - error=%1',
readMsg: 'Read %0 bytes from %1',
foundMsg: 'Found %0 tiddlers in %1',
nochangeMsg: "'%0' is up-to-date... skipped.",
lockedMsg: "'%0' is tagged '%1'... skipped.",
skippedMsg: 'skipped (cancelled by user)',
loadedMsg: 'Loaded %0 of %1 tiddlers from %2',
reportTitle: 'ImportedTiddlers',
warning: "Warning!! Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
handler: function(place,macroName,params) {
var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
var filter='updates';
if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
filter=params.shift();
var src=params.shift(); if (!src || !src.length) return; // filename is required
var quiet=(params[0]=='quiet'); if (quiet) params.shift();
var ask=(params[0]=='confirm'); if (ask) params.shift();
var force=(params[0]=='force'); if (force) params.shift();
var init=(params[0]=='init'); if (init) params.shift();
var nodirty=(params[0]=='nodirty'); if (nodirty) params.shift();
var norefresh=(params[0]=='norefresh'); if (norefresh) params.shift();
var noreport=(params[0]=='noreport'); if (noreport) params.shift();
this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as 'autotags'
if (label.trim().length) {
// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
createTiddlyButton(place,label.format([src.replace(/%20/g,' ')]),tip.format([src.replace(/%20/g,' ')]), function() {
if (src=='ask') src=prompt(this.askMsg);
config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
return false;
})
}
else {
// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
if (src=='ask') src=prompt(this.askMsg);
config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,nodirty:nodirty,norefresh:norefresh,noreport:noreport});
}
},
loadFile: function(src,callback,params) {
var quiet=params.quiet;
if (src==undefined || !src.length) return null; // filename is required
if (!quiet) clearMessage();
if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g,' ')]));
// if working locally and src is not a URL, read from local filesystem
if (document.location.protocol=='file:' && src.substr(0,5)!='http:' && src.substr(0,5)!='file:') {
var txt=loadFile(src);
if (!txt) { // file didn't load, might be relative path.. try fixup
var pathPrefix=document.location.href; // get current document path and trim off filename
var slashpos=pathPrefix.lastIndexOf('/'); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf('\\');
if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
src=pathPrefix+src;
if (pathPrefix.substr(0,5)!='http:') src=getLocalPath(src);
var txt=loadFile(src);
}
if (!txt) { // file still didn't load, report error
if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g,' '),'(unknown)']));
} else {
if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g,' ')]));
if (version.major+version.minor*.1+version.revision*.01!=2.52)
txt=convertUTF8ToUnicode(txt);
if (callback) callback(true,params,txt,src,null);
}
} else { // use XMLHttpRequest
doHttp('GET',src,null,null,config.options.txtRemoteUsername,config.options.txtRemotePassword,callback,params,null);
}
},
readTiddlersFromHTML: function(html) {
// for TW2.2+
if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
var remoteStore=new TiddlyWiki();
remoteStore.importTiddlyWiki(html);
return remoteStore.getTiddlers('title');
}
},
readTiddlersFromCSV: function(CSV) {
var remoteStore=new TiddlyWiki();
// GET NAMES
var lines=CSV.replace(/\r/g,'').split('\n');
var names=lines.shift().replace(/"/g,'').split(',');
CSV=lines.join('\n');
// ENCODE commas and newlines within quoted values
var comma='!~comma~!'; var commaRE=new RegExp(comma,'g');
var newline='!~newline~!'; var newlineRE=new RegExp(newline,'g');
CSV=CSV.replace(/"([^"]*?)"/g,
function(x){ return x.replace(/\,/g,comma).replace(/\n/g,newline); });
// PARSE lines
var lines=CSV.split('\n');
for (var i=0; i<lines.length; i++) { if (!lines[i].length) continue;
var values=lines[i].split(',');
// DECODE commas, newlines, and doubled-quotes, and remove enclosing quotes (if any)
for (var v=0; v<values.length; v++)
values[v]=values[v].replace(commaRE,',').replace(newlineRE,'\n')
.replace(/^"|"$/g,'').replace(/""/g,'"');
// EXTRACT tiddler values
var title=''; var text=''; var tags=[]; var fields={};
var created=null; var when=new Date(); var who=config.options.txtUserName;
for (var v=0; v<values.length; v++) { var val=values[v];
if (names[v]) switch(names[v].toLowerCase()) {
case 'title': title=val.replace(/\[\]\|/g,'_'); break;
case 'created': created=new Date(val); break;
case 'modified':when=new Date(val); break;
case 'modifier':who=val; break;
case 'text': text=val; break;
case 'tags': tags=val.readBracketedList(); break;
default: fields[names[v].toLowerCase()]=val; break;
}
}
// CREATE tiddler in temporary store
if (title.length)
remoteStore.saveTiddler(title,title,text,who,when,tags,fields,true,created||when);
}
return remoteStore.getTiddlers('title');
},
createTiddlerFromFile: function(src,txt) {
var t=new Tiddler();
var pos=src.lastIndexOf("/"); if (pos==-1) pos=src.lastIndexOf("\\");
t.title=pos==-1?src:src.substr(pos+1);
t.text=txt;
t.created=t.modified=new Date();
t.modifier=config.options.txtUserName;
if (src.substr(src.length-3,3)=='.js') t.tags=['systemConfig'];
return [t];
},
doImport: function(status,params,html,src,xhr) {
var cml=config.macros.loadTiddlers; // abbrev
src=src.split('?')[0]; // strip off "?nocache=..."
if (!status) {
displayMessage(cml.openErrMsg.format([src.replace(/%20/g,' '),xhr.status]));
return false;
}
var quiet=params.quiet;
var ask=params.ask;
var filter=params.filter;
var force=params.force;
var init=params.init;
var nodirty=params.nodirty;
var norefresh=params.norefresh;
var noreport=params.noreport;
var tiddlers = cml.readTiddlersFromHTML(html);
if (!tiddlers||!tiddlers.length) tiddlers=cml.readTiddlersFromCSV(html);
if (!tiddlers||!tiddlers.length) tiddlers=cml.createTiddlerFromFile(src,html);
var count=tiddlers?tiddlers.length:0;
if (!quiet) displayMessage(cml.foundMsg.format([count,src.replace(/%20/g,' ')]));
var wasDirty=store.isDirty();
store.suspendNotifications();
var count=0;
if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
var inbound = tiddlers[t];
var theExisting = store.getTiddler(inbound.title);
if (inbound.title==cml.reportTitle)
continue; // skip 'ImportedTiddlers' history from the other document...
if (theExisting && theExisting.tags.contains(cml.lockedTag)) {
if (!quiet) displayMessage(cml.lockedMsg.format([theExisting.title,cml.lockedTag]));
continue; // skip existing tiddler if tagged with 'noReload'
}
// apply the all/new/changes/updates filter (if any)
if (filter && filter!='all') {
if ((filter=='new') && theExisting) // skip existing tiddlers
continue;
if ((filter=='changes') && !theExisting) // skip new tiddlers
continue;
if ((filter.substr(0,4)=='tag:') && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
continue;
if ((filter.substr(0,8)=='tiddler:') && inbound.title!=filter.substr(8)) // must match specific tiddler name
continue;
if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0)) {
var msg=cml.nochangeMsg;
if (!quiet&&msg.length) displayMessage(msg.format([inbound.title]));
continue;
}
}
// get confirmation if required
var msg=(theExisting?'Update':'Add')+" tiddler '"+inbound.title+"'\n"
+'from '+src.replace(/%20/g,' ')+'\n\nOK to proceed?';
if (ask && !confirm(msg))
{ tiddlers[t].status=cml.skippedMsg; continue; }
// DO IT!
var tags=new Array().concat(inbound.tags,cml.newTags);
store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier,
inbound.modified, tags, inbound.fields, true, inbound.created);
// force creation date to imported value - needed for TW2.1.3 or earlier
store.fetchTiddler(inbound.title).created = inbound.created;
tiddlers[t].status=theExisting?'updated':'added'
if (init && tags.contains('systemConfig') && !tags.contains('systemConfigDisable')) {
var ok=true;
if (ask||!quiet) ok=confirm(cml.warning.format([inbound.title]))
if (ok) { // run the plugin
try { window.eval(inbound.text); tiddlers[t].status+=' (plugin initialized)'; }
catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
}
}
count++;
}
store.resumeNotifications();
if (count) {
// set/clear 'unsaved changes' flag, refresh page display, and generate a report
store.setDirty(wasDirty||!nodirty);
if (!norefresh) {
story.forEachTiddler(function(t,e){
if(!story.isDirty(t))story.refreshTiddler(t,null,true)
});
store.notifyAll();
}
if (!noreport) cml.report(src,tiddlers,count,quiet);
}
// show message whenver tiddlers are actually loaded
if (!quiet||count)
displayMessage(cml.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g,' ')]));
},
showReport: true,
report: function(src,tiddlers,count,quiet) {
var cml=config.macros.loadTiddlers; // abbrev
// format the new report content
var newText = 'On '+(new Date()).toLocaleString()+', ';
newText += config.options.txtUserName+' loaded '+count+' tiddlers ';
newText += 'from\n[['+src+'|'+src+']]:\n';
newText += '<<<\n';
for (var t=0; t<tiddlers.length; t++)
if (tiddlers[t].status)
newText += '#[['+tiddlers[t].title+']] - '+tiddlers[t].status+'\n';
newText += '<<<\n';
var title=cml.reportTitle;
var currText='';
var t=store.getTiddler(title);
if (t) currText=(t.text.length?'\n----\n':'')+t.text;
store.saveTiddler(title, title, newText+currText,
config.options.txtUserName, new Date(), t?t.tags:null, t?t.fields:null);
if (!quiet) {
if (config.options.chkLoadTiddlersShowReport)
story.displayTiddler(null,title);
story.refreshTiddler(title,null,true);
}
}
}
//}}}
/***
|Name|LoadTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.8.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for LoadTiddlersPlugin|
!!!!!Usage
<<<
Syntax:
{{{<<loadTiddlers label:text prompt:text filter source quiet confirm force init noreport tag tag tag...>>}}}
Example:
{{{<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>}}}
<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>
Where:
''"""label:text"""'' and ''"""prompt:text"""''
>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing. If a label is NOT provided, then no link is created and the loadTiddlers function is performed whenever the containing tiddler is rendered.
''filter'' (optional) determines which tiddlers will be automatically selected for importing. Use one of the following keywords:
>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler
>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)
>''""""tiddler:TiddlerName""""'' retrieves only the specific tiddler named in the parameter.
>''""""tag:text""""'' retrieves only the tiddlers tagged with the indicated text.
>> Note: ''if an existing tiddler is tagged with 'noReload', then it will not be overwritten'', even if the inbound tiddler has been selected by the filtering process. This allows you to make local changes to imported tiddlers while ensuring that those changes won't be lost due to automatic tiddler updates retrieved from the import source document.
''source'' (required) is the location of the imported document. It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")
>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked
''"quiet"'' (optional)
>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.
''"confirm"'' (optional)
>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.
''"init"'' (optional)
>invoke tiddlers tagged with <<tag systemConfig>> as plugins as soon as they are imported, without requiring a save-and-reload action first. For safety, a browser message box (OK/Cancel) is displayed for each imported plugin, so that you can manually bypass any plugins that you do not want to invoke. Note, however, that those tiddlers are still //imported// into your document and therefore will still take effect the next time you save-and-reload the document.
''"force"'' (optional)
>import all matching tiddlers, even if unchanged
''"noreport"'' (optional)
>suppress generation of [[ImportedTiddlers]] report
''"tag tag tag..."'' (optional)
>any remaining parameters are used as tag values to be added to each imported tiddler (i.e., "tag-on-import")
<<<
!!!!!Configuration
<<<
<<option chkLoadTiddlersShowReport>>after loading tiddlers, automatically display [[ImportedTiddlers]] (if created)
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2009.10.08 3.8.1 removed switchTheme() from doImport()... causes an INFINITE cycle of imports!
2009.10.06 3.8.0 added createTiddlerFromFile (import text files)
2009.10.04 3.7.8 in doImport(), call switchTheme() after loading tiddlers
2009.09.27 3.7.7 in readTiddlersFromCSV(), strip \r from input and fixed handling for quoted values
2009.09.01 3.7.6 added config.options.chkLoadTiddlersShowReport (default=true)
2009.09.01 3.7.6 added config.options.chkLoadTiddlersShowReport (default=true)
2009.08.30 3.7.5 in doImport(), check status and report error, if any
2009.08.29 3.7.4 in handler(), added 'return false' in button function (fixes IE page transition)
2009.08.19 3.7.3 in doImport(), fixed 'init' handling
2009.08.16 3.7.2 in doImport(), corrected check for tiddlers returned by readTiddlersFromHTML();
2009.07.03 3.7.1 fixups for TW252: doHttp() doesn't return XHR and convertUTF8ToUnicode() not needed for local I/O
2009.05.04 3.7.0 read CSV file format
2008.11.14 3.6.4 in loadFile(), force use of XMLHttpRequest if not viewing a local document (supports use of relative file references when online)
2008.10.27 3.6.3 in doImport(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
2008.08.05 3.6.2 rewrote loadFile() to eliminate use of platform-specific fileExists() test
2008.08.03 3.6.1 in handler(), changed variable 'prompt' to 'tip' to avoid conflict with prompt() function
2008.01.07 3.6.0 added 'init' option to automatically invoke plugin tiddlers as soon as they are loaded (without needing save/reload)
2008.01.03 3.5.0 in loadFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.12.04 *.*.* update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.27 3.4.8 added missing 'fields' params to saveTiddler() call. Fixes problem where importing tiddlers would lose the custom fields.
2007.06.25 3.4.7 add calls to store.suspendNotifications() and store.resumeNotifications() to eliminate redisplay overhead DURING import activities.
2007.05.27 3.4.6 in handler(), loadRemoteFile() and doImport(), added 'noreport' flag to suppress generation of ImportedTiddlers
2007.05.27 3.4.5 in handler(), initialize 'newTags' to [] (empty array) instead of null... fixes fatal error when loading tiddler without autotagging.
2007.04.22 3.4.4 in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content. Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.04.05 3.4.3 in doImport(), changed this.readTiddlersFromHTML(html) to config.macros.loadTiddlers.readTiddlersFromHTML(html).
2007.03.26 3.4.2 renamed import() to doImport() to fix IE load-time error ("identifier expected"). "import" is a reserved word in some browsers...
2007.03.22 3.4.1 code cleanup: moved all functions inside object def'n, re-wrote report function
2007.03.21 3.4.0 split ImportTiddlersPlugin and LoadTiddlersPlugin into separate plugins
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 1.0.0 Initial Release
<<<
/***
These tweaks are from www.tiddlytools.com. Not all of the tweaks on that site are included here, so it is named LocalCoreTweaks so
that it is not updated from the original sire (because of the name change).
***/
/***
!!!529 IE fixup - case-sensitive element lookup of tiddler elements
***/
/***
http://trac.tiddlywiki.org/ticket/529 - OPEN
This tweak hijacks the standard browser function, document.getElementById(), to work-around the case-INsensitivity error in Internet Explorer (all versions up to and including IE7) //''Note: This tweak is only applied when using IE, and only for lookups of rendered tiddler elements within the containing 'tiddlerDisplay' element.''//
***/
//{{{
if (config.browser.isIE) {
document.coreTweaks_coreGetElementById=document.getElementById;
document.getElementById=function(id) {
var e=document.coreTweaks_coreGetElementById(id);
if (!e || !e.parentNode || e.parentNode.id!='tiddlerDisplay') return e;
for (var i=0; i<e.parentNode.childNodes.length; i++)
if (id==e.parentNode.childNodes[i].id) return e.parentNode.childNodes[i];
return null;
};
}
//}}}
/***
!!! 1134 handle references to tiddler sections in shadows
***/
/***
http://trac.tiddlywiki.org/ticket/1134
This tweak REPLACES and extends {{{store.getTiddlerText()}}} so it can return sections defined in shadow tiddlers. It also permits use of leading whitespace in section headings.
***/
//{{{
TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
{
if(!title) return defaultText;
var parts = title.split(config.textPrimitives.sectionSeparator);
var title = parts[0];
var section = parts[1];
var parts = title.split(config.textPrimitives.sliceSeparator);
var title = parts[0];
var slice = parts[1]?this.getTiddlerSlice(title,parts[1]):null;
if(slice) return slice;
var tiddler = this.fetchTiddler(title);
var text = defaultText;
if(this.isShadowTiddler(title))
text = this.getShadowTiddlerText(title);
if(tiddler)
text = tiddler.text;
if(!section) return text;
var re = new RegExp("(^!{1,6}[ \t]*" + section.escapeRegExp() + "[ \t]*\n)","mg");
re.lastIndex = 0;
var match = re.exec(text);
if(match) {
var t = text.substr(match.index+match[1].length);
var re2 = /^!/mg;
re2.lastIndex = 0;
match = re2.exec(t); //# search for the next heading
if(match)
t = t.substr(0,match.index-1);//# don't include final \n
return t;
}
return defaultText;
};
//}}}
[[Welcome]]
[[ToolIndex]]
--------
<<tiddler ShowPopup with: [[BookmarkList]] "Bookmarks" "User's list of bookmarked tiddlers." >> @@font-size: smaller;[[(edit)|BookmarkList]]@@
--------
<<toggleSideBar "Toggle Right Bar" '' show>>
--------
<<tiddler InstructorMainMenu>>
!Presentations
<<openStory list "Presentation" >>
<<tiddler PresentationList>>
!Chapters
<<openStory list "Chapter" >>
<<tiddler ChapterList>>
!Quizzes
<<tiddler QuizList>>
/***
|Name|MatchTagsPlugin|
|Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
|Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|'tag matching' with full boolean expressions (AND, OR, NOT, and nested parentheses)|
!!!!!Documentation
> see [[MatchTagsPluginInfo]]
!!!!!Revisions
<<<
2009.08.29 [2.0.1] added support for {{{config.macros.matchTags.defTags}}} to auto-tag [[MatchingTiddlers]] output
| please see [[MatchTagsPluginInfo]] for additional revision details |
2008.02.28 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.MatchTagsPlugin= {major: 2, minor: 0, revision: 1, date: new Date(2009,8,29)};
// store.getMatchingTiddlers() processes boolean expressions for tag matching
// sortfield (optional) sets sort order for tiddlers - default=title
// tiddlers (optional) use alternative set of tiddlers (instead of current store)
TiddlyWiki.prototype.getMatchingTiddlers = function(tagexpr,sortfield,tiddlers) {
var debug=config.options.chkDebug; // abbreviation
var cmm=config.macros.matchTags; // abbreviation
var r=[]; // results are an array of tiddlers
var tids=tiddlers||store.getTiddlers(sortfield||"title");
if (tiddlers && sortfield) store.sortTiddlers(tids,sortfield);
if (debug) displayMessage(cmm.msg1.format([tids.length]));
// try simple lookup to quickly find single tags or tags that
// contain boolean operators as literals, e.g. "foo and bar"
for (var t=0; t<tids.length; t++)
if (tids[t].isTagged(tagexpr)) r.pushUnique(tids[t]);
if (r.length) {
if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
return r;
}
// convert expression into javascript code with regexp tests,
// so that "tag1 AND ( tag2 OR NOT tag3 )" becomes
// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag3\~/.test(...) )"
// normalize whitespace, tokenize operators, delimit with "~"
var c=tagexpr.trim(); // remove leading/trailing spaces
c = c.replace(/\s+/ig," "); // reduce multiple spaces to single spaces
c = c.replace(/\(\s?/ig,"~(~"); // open parens
c = c.replace(/\s?\)/ig,"~)~"); // close parens
c = c.replace(/(\s|~)?&&(\s|~)?/ig,"~&&~"); // &&
c = c.replace(/(\s|~)AND(\s|~)/ig,"~&&~"); // AND
c = c.replace(/(\s|~)?\|\|(\s|~)?/ig,"~||~"); // ||
c = c.replace(/(\s|~)OR(\s|~)/ig,"~||~"); // OR
c = c.replace(/(\s|~)?!(\s|~)?/ig,"~!~"); // !
c = c.replace(/(^|~|\s)NOT(\s|~)/ig,"~!~"); // NOT
c = c.replace(/(^|~|\s)NOT~\(/ig,"~!~("); // NOT(
// change tag terms to regexp tests
var terms=c.split("~"); for (var i=0; i<terms.length; i++) { var t=terms[i];
if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
if (t==config.macros.matchTags.untaggedKeyword)
terms[i]="tiddlertags=='~~'"; // 'untagged' tiddlers
else
terms[i]="/\\~"+t+"\\~/.test(tiddlertags)";
}
c=terms.join(" ");
if (debug) { displayMessage(cmm.msg2.format([tagexpr])); displayMessage(cmm.msg3.format([c])); }
// scan tiddlers for matches
for (var t=0; t<tids.length; t++) {
// assemble tags from tiddler into string "~tag1~tag2~tag3~"
var tiddlertags = "~"+tids[t].tags.join("~")+"~";
try { if(eval(c)) r.push(tids[t]); } // test tags
catch(e) { // error in test
displayMessage(cmm.msg2.format([tagexpr]));
displayMessage(cmm.msg3.format([c]));
displayMessage(e.toString());
break; // skip remaining tiddlers
}
}
if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
return r;
}
//}}}
//{{{
config.macros.matchTags = {
msg1: "scanning %0 input tiddlers",
msg2: "looking for '%0'",
msg3: "using expression: '%0'",
msg4: "found %0 tiddlers matching '%1'",
noMatch: "no matching tiddlers",
untaggedKeyword: "-",
untaggedLabel: "no tags",
untaggedPrompt: "show tiddlers with no tags",
defTiddler: "MatchingTiddlers",
defTags: "",
defFormat: "%0",
defSeparator: "\n",
reportHeading: "Found %0 tiddlers tagged with: '{{{%1}}}'\n----\n",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var mode=params[0]?params[0].toLowerCase():'';
if (mode=="inline")
params.shift();
if (mode=="report" || mode=="panel") {
params.shift();
var target=params.shift()||this.defTiddler;
}
if (mode=="popup") {
params.shift();
if (params[0]&¶ms[0].substr(0,6)=="label:") var label=params.shift().substr(6);
if (params[0]&¶ms[0].substr(0,7)=="prompt:") var prompt=params.shift().substr(7);
} else {
var fmt=(params.shift()||this.defFormat).unescapeLineBreaks();
var sep=(params.shift()||this.defSeparator).unescapeLineBreaks();
}
var sortBy="+title";
if (params[0]&¶ms[0].substr(0,5)=="sort:") sortBy=params.shift().substr(5);
var expr = params.join(" ");
if (mode!="panel" && (!expr||!expr.trim().length)) return;
if (expr==this.untaggedKeyword)
{ var label=this.untaggedLabel; var prompt=this.untaggedPrompt };
switch (mode) {
case "popup": this.createPopup(place,label,expr,prompt,sortBy); break;
case "panel": this.createPanel(place,expr,fmt,sep,sortBy,target); break;
case "report": this.createReport(target,this.defTags,expr,fmt,sep,sortBy); break;
case "inline": default: this.createInline(place,expr,fmt,sep,sortBy); break;
}
},
formatList: function(tids,fmt,sep) {
var out=[];
for (var t=0; t<tids.length; t++) {
var title="[["+tids[t].title+"]]";
var who=tids[t].modifier;
var when=tids[t].modified.toLocaleString();
var text=tids[t].text;
var first=tids[t].text.split("\n")[0];
var desc=store.getTiddlerSlice(tids[t].title,"description");
desc=desc||store.getTiddlerSlice(tids[t].title,"Description");
desc=desc||store.getTiddlerText(tids[t].title+"##description");
desc=desc||store.getTiddlerText(tids[t].title+"##Description");
out.push(fmt.format([title,who,when,text,first,desc]));
}
return out.join(sep);
},
createInline: function(place,expr,fmt,sep,sortBy) {
wikify(this.formatList(store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy),fmt,sep),place);
},
createPopup: function(place,label,expr,prompt,sortBy) {
var btn=createTiddlyButton(place,
(label||expr).format([expr]),
(prompt||config.views.wikified.tag.tooltip).format([expr]),
function(ev){ return config.macros.matchTags.showPopup(this,ev||window.event); });
btn.setAttribute("sortBy",sortBy);
btn.setAttribute("expr",expr);
},
showPopup: function(here,ev) {
var p=Popup.create(here); if (!p) return false;
var tids=store.getMatchingTiddlers(here.getAttribute("expr"));
store.sortTiddlers(tids,here.getAttribute("sortBy"));
var list=[]; for (var t=0; t<tids.length; t++) list.push(tids[t].title);
if (!list.length) createTiddlyText(p,this.noMatch);
else {
var b=createTiddlyButton(createTiddlyElement(p,"li"),
config.views.wikified.tag.openAllText,
config.views.wikified.tag.openAllTooltip,
function() {
var list=this.getAttribute("list").readBracketedList();
story.displayTiddlers(null,tids);
});
b.setAttribute("list","[["+list.join("]] [[")+"]]");
createTiddlyElement(p,"hr");
}
var out=this.formatList(tids," %0 ","\n"); wikify(out,p);
Popup.show();
ev.cancelBubble=true;
if(ev.stopPropagation) ev.stopPropagation();
return false;
},
createReport: function(target,tags,expr,fmt,sep,sortBy) {
var tids=store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy);
if (!tids.length) { displayMessage('no matches for: '+expr); return false; }
var msg=config.messages.overwriteWarning.format([target]);
if (store.tiddlerExists(target) && !confirm(msg)) return false;
var out=this.reportHeading.format([tids.length,expr])
out+=this.formatList(tids,fmt,sep);
store.saveTiddler(target,target,out,config.options.txtUserName,new Date(),tags,{});
story.closeTiddler(target); story.displayTiddler(null,target);
},
createPanel: function(place,expr,fmt,sep,sortBy,tid) {
var s=createTiddlyElement(place,"span"); s.innerHTML=store.getTiddlerText("MatchTagsPlugin##html");
var f=s.getElementsByTagName("form")[0];
f.expr.value=expr; f.fmt.value=fmt; f.sep.value=sep.escapeLineBreaks();
f.tid.value=tid; f.tags.value=this.defTags;
}
};
//}}}
/***
//{{{
!html
<form style='display:inline;white-space:nowrap'>
<input type='text' name='expr' style='width:50%' title='tag expression'><!--
--><input type='text' name='fmt' style='width:10%' title='list item format'><!--
--><input type='text' name='sep' style='width:5%' title='list item separator'><!--
--><input type='text' name='tid' style='width:12%' title='target tiddler title'><!--
--><input type='text' name='tags' style='width:10%' title='target tiddler tags'><!--
--><input type='button' name='go' style='width:8%' value='go' onclick="
var expr=this.form.expr.value;
if (!expr.length) { alert('Enter a boolean tag expression'); return false; }
var fmt=this.form.fmt.value;
if (!fmt.length) { alert('Enter the list item output format'); return false; }
var sep=this.form.sep.value.unescapeLineBreaks();
var tid=this.form.tid.value;
if (!tid.length) { alert('Enter a target tiddler title'); return false; }
var tags=this.form.tags.value;
config.macros.matchTags.createReport(tid,tags,expr,fmt,sep,'title');
return false;">
</form>
!end
//}}}
***/
//{{{
// SHADOW TIDDLER for displaying default panel input form
config.shadowTiddlers.MatchTags="<<matchTags panel>>";
//}}}
//{{{
// TWEAK core filterTiddlers() for enhanced boolean matching in [tag[...]] syntax:
// use getMatchingTiddlers instead getTaggedTiddlers
var fn=TiddlyWiki.prototype.filterTiddlers;
fn=fn.toString().replace(/getTaggedTiddlers/g,"getMatchingTiddlers");
eval("TiddlyWiki.prototype.filterTiddlers="+fn);
//}}}
//{{{
// REDEFINE core handler for enhanced boolean matching in tag:"..." paramifier
// use filterTiddlers() instead of getTaggedTiddlers() to get list of tiddlers.
config.paramifiers.tag = {
onstart: function(v) {
var tagged = store.filterTiddlers("[tag["+v+"]]");
story.displayTiddlers(null,tagged,null,false,null);
}
};
//}}}
/***
|Name|MatchTagsPluginInfo|
|Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
|Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
|Version|2.0.1|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for MatchTagsPlugin|
!!!!!Usage
<<<
This plugin extends the {{{[tag[tagname]]}}} macro parameter syntax used by the TiddlyWiki core {{{<<list>>}}} macro so that, instead of a simple tagname value, you can specify a complex combination of tagname values using a //boolean expression// containing AND, OR, and NOT operators, enclosed in nested parentheses if needed.
{{{
<<list filter "[tag[expression]]">>
}}}
In addition, the plugin defines a new macro, {{{<<matchTags ...>>}}} that can be used instead of the core {{{<<list>>}}} macro to output a list of matching tiddlers //using a custom 'item format' and 'separator'//. You can also use this macro to create a command link that displays the matching tiddlers within a popup list, similar to the standard {{{<<tag tagName>>}}} macro, but matching a combination of tag values rather than a single tag value.
{{{
<<matchTags inline "format" "separator" sort:fieldname tag expression>>
<<matchTags popup "label:..." "prompt:..." sort:fieldname tag expression>>
<<matchTags report TiddlerName "format" "separator" sort:fieldname tag expression>>
<<matchTags panel Tiddlername "format" "separator" sort:fieldname tag expression>>
}}}
where:
* ''inline'', ''report'', ''panel'', and ''popup''<br>are keywords that indicate the type of output that the macro should produce:
** ''inline'' //(default)// - displays a list of matching tiddlers embedded directly in tiddler content
** ''popup'' - embeds a command button that, when clicked, lists matching tiddlers in a ~TiddlyWiki popup display
** ''report'' - generates a list of matching tiddler in a separate [[MatchingTiddlers]] report tiddler
** ''panel'' - displays an interactive form for generating a [[MatchingTiddlers]] report
* ''format''<br>defines the wiki-syntax for rendering list items. The following //substitution markers// can be used to insert tiddler-specific information for each matched tiddler:
** {{{%0}}} - title
** {{{%1}}} - modifier (author)
** {{{%2}}} - modified (date of last change)
** {{{%3}}} - text (all tiddler content)
** {{{%4}}} - firstline (tiddler content up to the first newline)
** {{{%5}}} - description (tiddler slice or section content named "description" or "Description")
* ''separator''<br>defines the wiki-syntax to use //between// each matching title (e.g., ", " creates a comma-separated list, while "\n" displays one tiddler per line).
* ''sort:fieldname'' (optional)<br>specifies the sort order for the resulting list of tiddlers. You can specify any tiddler field name (standard or custom-defined). Standard tiddler fieldnames include: //title, created, modified, modifier//. If not specified, tiddlers are sorted by title. You can prefix the fieldname with "+" or "-" to indicate ascending or descending order, respectively.
* ''tag expression''<br>the remaining parameter(s) are joined together to define the boolean expression to be matched.
When using the ''popup'' option, there are two additional (and optional) parameters you can specify:
* ''"label:..."''(optional)<br> indicates the text for the popup command link. The default is to display the specified tag expression itself.
* ''"prompt:..."'' (optional)<br>indicates the mouseover 'tooltip' for the popup command link.
When using the ''report'' or ''panel'' option, an additional parameter may be provided:
* ''~TiddlerName''<br>specifies the target tiddler into which the output will be generated (default: [[MatchingTiddlers]])
Notes:
*A tag expression can use any combination of text operators: ''AND'', ''OR'', ''NOT'' (or their equivalent javascript operators: ''&&'', ''||'', ''!''), contained in nested parentheses as needed.
*Operators should be delimited by spaces or parentheses.
*Before matching, leading/trailing spaces are automatically trimmed and multiple spaces are reduced to single spaces.
*Tag values containing embedded spaces do //not// have to be enclosed in {{{[[...]]}}}.
*Tag values that contain boolean operators as ''literal text'' (e.g., {{{"foo and bar"}}} or {{{"foo && bar"}}} cannot be used within a compound boolean expression, but //can// be matched if specified by themselves, without any other tag values or operators.
*To match tiddlers that are untagged, use "-" as a special tag value within the expression.
*You can match "wildcard" tags by using //regular expression// (i.e., "text pattern") syntax within a tag value, e.g. {{{[Tt]agvalue.*}}}
<<<
!!!!!Examples:
<<<
display a popup list:
{{{
<<matchTags popup sample OR (settings AND systemConfig)>>
}}}
><<matchTags popup sample OR (settings AND systemConfig)>>
display a popup list with custom label:
{{{
<<matchTags popup "label:samples and settings" sample OR (settings AND systemConfig)>>
}}}
><<matchTags popup "label:samples and settings" sample OR (settings AND systemConfig)>>
display a popup list of untagged tiddlers:
{{{
<<matchTags popup ->>
}}}
><<matchTags popup ->>
generate a report using interactive form control panel
{{{
<<matchTags panel "MatchingTiddlers" "%0" "\n" sample OR (settings AND systemConfig)>>
}}}
>{{smallform{<<matchTags panel "MatchingTiddlers" "%0" "\n" sample OR (settings AND systemConfig)>>}}}
comma-separated list:
{{{
<<matchTags "%0" ", " sample OR (settings AND systemConfig)>>
}}}
><<matchTags "%0" ", " sample OR (settings AND systemConfig)>>
numbered list (sorted by modification date, most recent first):
{{{
<<matchTags "#%0 (%2)<br>^^%5^^" "\n" sort:-modified sample OR (settings AND systemConfig)>>
}}}
><<matchTags "#%0 (%2)<br>^^%5^^" "\n" sort:-modified sample OR (settings AND systemConfig)>>
bullet-item list (using the TiddlyWiki core {{{<<list filter ...>>}}} macro):
//(Note: when using the core {{{<<list>>}}} macro, you should always enclose the entire tag filter parameter within quotes)//
{{{
<<list filter "[tag[sample OR (settings AND systemConfig)]]">>
}}}
><<list filter "[tag[sample OR (settings AND systemConfig)]]">>
<<<
!!!!!Revisions
<<<
2009.08.29 [2.0.1] added support for {{{config.macros.matchTags.defTags}}} to auto-tag [[MatchingTiddlers]] output
2008.09.04 [2.0.0] added "report" and "panel" options to generate formatted results and store in a tiddler. Also, added config.macros.matchTags.formatList(place,fmt,sep) API to return formatted output for use with other plugins/scripts
2008.09.01 [1.9.2] fixed return value from popup button handler so IE doesn't attempt to leave the page
2008.08.31 [1.9.1] improved expression conversion handling to permit use of regular expressions for "wildcard" matching within tag values
2008.06.12 [1.9.0] added support for formatted output of: title, who, when, text, firstline, description (slice or section)
2008.06.05 [1.8.0] in getMatchingTiddlers(), added optional sortfield and tiddlers params to support use of alternative set of tiddlers instead of using current store content (provides filtering support for ImportTiddlersPlugin)
2008.06.04 [1.7.1] in getMatchingTiddlers(), reworked conversion of expression for more robust parsing of whitespace, parentheses and javascript operators and allow use of "-" (untagged) //within// expressions
2008.05.19 [1.7.0] in getMatchingTiddlers(), use reverseLookup() instead of forEachTiddler() to permit access to tiddlers included via [[IncludePlugin|http://tiddlywiki.abego-software.de/#IncludePlugin]]
2008.05.17 [1.6.0] in getMatchingTiddlers(), rewrote expression conversion to handle tags with spaces tag values that are substrings of other tag values.
2008.05.16 [1.5.0] added special case using "-" to find UNTAGGED tiddlers
2008.05.15 [1.4.0] added "popup" output option
2008.05.14 [1.3.4] instead of hijacking getTaggedTiddlers(), added tweak of filterTiddlers() prototype to replace getTaggedTiddlers() with getMatchingTiddler() so that core use of getTaggedTiddlers() does not perform boolean processing of tiddler titles such as [[To Be or not To Be]]. Also, improved "filter error" messages in getMatchingTiddlers() to report tag expression in addition to actual eval error.
2008.04.25 [1.3.3] in getTaggedTiddlers(), fixed handling for "not" embedded within a tag
2008.04.21 [1.3.2] in getTaggedTiddlers(), fixed handling for initial "NOT" and "NOT(expr)" syntax
2008.04.20 [1.3.1] in getTaggedTiddlers(), corrected check for boolean expression to avoid excess processing of tags containing spaces. Also, improved handling for non-existing tags that contain text of existing tags
2008.04.19 [1.3.0] in filterTiddlers(), use getTaggedTiddlers() instead of matchTags(), and then hijack getTaggedTiddlers() to add matchTags() handling
2008.04.19 [*.*.*] plugin size reduction: moved documentation to [[MatchTagsPluginInfo]]
2008.03.25 [1.2.0] added optional "sort:fieldname" parameter
2008.03.20 [1.1.2] in handler(), replace 'encodeTiddlyLink' with explicit [[...]] brackets to ensure that one-word tiddler titles are properly rendered as TiddlyLinks
2008.02.29 [1.1.1] in matchTags(), added handling to skip remaining tiddlers if expression has an error
2008.02.29 [1.1.0] refactored to define store.matchTags() and extend store.filterTiddlers()
2008.02.28 [1.0.0] initial release
<<<
!What is ~MindMapping?
{{overlay1{[[Wikipedia|http://en.wikipedia.org/wiki/Mind_map]]:
<<<
A mind map is a diagram used to represent words, ideas, tasks, or other items linked to and arranged around a central key word or idea. Mind maps are used to generate, visualize, structure, and classify ideas, and as an aid in study, organization, problem solving, decision making, and writing.
<<<
}}}
{{overlay2{
!!Use Cases
}}}
<html>
<hide linebreaks>
<ul>
<li class="overlay2">Outlining</li>
<li class="overlay3">Process design/diagram</li>
<li class="overlay4">Project management</li>
<li class="overlay5">Brainstorming</li>
<li class="overlay6">Structured notebook</li>
</ul>
</html>
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!Configuration
<<<
<<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
>Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
>In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class). In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release. Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};
// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkFloatingSlidersAnimate===undefined)
config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE
// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");
// if removeCookie() function is not defined by TW core, define it here.
if (window.removeCookie===undefined) {
window.removeCookie=function(name) {
document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
}
}
config.formatters.push( {
name: "nestedSliders",
match: "\\n?\\+{3}",
terminator: "\\s*\\={3}\\n?",
lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\>]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\>)?(\\.\\.\\.)?\\s*",
handler: function(w)
{
lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
{
var defopen=lookaheadMatch[1];
var cookiename=lookaheadMatch[2];
var header=lookaheadMatch[3];
var panelwidth=lookaheadMatch[4];
var transient=lookaheadMatch[5];
var hover=lookaheadMatch[6];
var buttonClass=lookaheadMatch[7];
var label=lookaheadMatch[8];
var openlabel=lookaheadMatch[9];
var panelID=lookaheadMatch[10];
var blockquote=lookaheadMatch[11];
var deferred=lookaheadMatch[12];
// location for rendering button and panel
var place=w.output;
// default to closed, no cookie, no accesskey, no alternate text/tip
var show="none"; var cookie=""; var key="";
var closedtext=">"; var closedtip="";
var openedtext="<"; var openedtip="";
// extra "+", default to open
if (defopen) show="block";
// cookie, use saved open/closed state
if (cookiename) {
cookie=cookiename.trim().slice(1,-1);
cookie="chkSlider"+cookie;
if (config.options[cookie]==undefined)
{ config.options[cookie] = (show=="block") }
show=config.options[cookie]?"block":"none";
}
// parse label/tooltip/accesskey: [label=X|tooltip]
if (label) {
var parts=label.trim().slice(1,-1).split("|");
closedtext=parts.shift();
if (closedtext.substr(closedtext.length-2,1)=="=")
{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
openedtext=closedtext;
if (parts.length) closedtip=openedtip=parts.join("|");
else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
}
// parse alternate label/tooltip: [label|tooltip]
if (openlabel) {
var parts=openlabel.trim().slice(1,-1).split("|");
openedtext=parts.shift();
if (parts.length) openedtip=parts.join("|");
else openedtip="hide "+openedtext;
}
var title=show=='block'?openedtext:closedtext;
var tooltip=show=='block'?openedtip:closedtip;
// create the button
if (header) { // use "Hn" header format instead of button/link
var lvl=(header.length>5)?5:header.length;
var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,buttonClass,title);
btn.onclick=onClickNestedSlider;
btn.setAttribute("href","javascript:;");
btn.setAttribute("title",tooltip);
}
else
var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
btn.innerHTML=title; // enables use of HTML entities in label
// set extra button attributes
btn.setAttribute("closedtext",closedtext);
btn.setAttribute("closedtip",closedtip);
btn.setAttribute("openedtext",openedtext);
btn.setAttribute("openedtip",openedtip);
btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
btn.defOpen=defopen!=null; // save default open/closed state (boolean)
btn.keyparam=key; // save the access key letter ("" if none)
if (key.length) {
btn.setAttribute("accessKey",key); // init access key
btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
}
btn.setAttribute("hover",hover?"true":"false");
btn.onmouseover=function(ev) {
// optional 'open on hover' handling
if (this.getAttribute("hover")=="true" && this.sliderPanel.style.display=='none') {
document.onclick.call(document,ev); // close transients
onClickNestedSlider(ev); // open this slider
}
// mouseover on button aligns floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
}
// create slider panel
var panelClass=panelwidth?"floatingPanel":"sliderPanel";
if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
panel.button = btn; // so the slider panel know which button it belongs to
btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
panel.defaultPanelWidth=(panelwidth && panelwidth.length>2)?panelwidth.slice(1,-1):"";
panel.setAttribute("transient",transient=="*"?"true":"false");
panel.style.display = show;
panel.style.width=panel.defaultPanelWidth;
panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }
// render slider (or defer until shown)
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
if ((show=="block")||!deferred) {
// render now if panel is supposed to be shown or NOT deferred rendering
w.subWikify(blockquote?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
// align floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
}
else {
var src = w.source.substr(w.nextMatch);
var endpos=findMatchingDelimiter(src,"+++","===");
panel.setAttribute("raw",src.substr(0,endpos));
panel.setAttribute("blockquote",blockquote?"true":"false");
panel.setAttribute("rendered","false");
w.nextMatch += endpos+3;
if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
}
}
}
}
)
function findMatchingDelimiter(src,starttext,endtext) {
var startpos = 0;
var endpos = src.indexOf(endtext);
// check for nested delimiters
while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
// count number of nested 'starts'
var startcount=0;
var temp = src.substring(startpos,endpos-1);
var pos=temp.indexOf(starttext);
while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
// set up to check for additional 'starts' after adjusting endpos
startpos=endpos+endtext.length;
// find endpos for corresponding number of matching 'ends'
while (startcount && endpos!=-1) {
endpos = src.indexOf(endtext,endpos+endtext.length);
startcount--;
}
}
return (endpos==-1)?src.length:endpos;
}
//}}}
//{{{
window.onClickNestedSlider=function(e)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
while (theTarget && theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
if (!theTarget) return false;
var theSlider = theTarget.sliderPanel;
var isOpen = theSlider.style.display!="none";
// if SHIFT-CLICK, dock panel first (see [[MoveablePanelPlugin]])
if (e.shiftKey && config.macros.moveablePanel) config.macros.moveablePanel.dock(theSlider,e);
// toggle label
theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
// toggle tooltip
theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));
// deferred rendering (if needed)
if (theSlider.getAttribute("rendered")=="false") {
var place=theSlider;
if (theSlider.getAttribute("blockquote")=="true")
place=createTiddlyElement(place,"blockquote");
wikify(theSlider.getAttribute("raw"),place);
theSlider.setAttribute("rendered","true");
}
// show/hide the slider
if(config.options.chkAnimate && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
else
theSlider.style.display = isOpen ? "none" : "block";
// reset to default width (might have been changed via plugin code)
theSlider.style.width=theSlider.defaultPanelWidth;
// align floater panel position with target button
if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);
// if showing panel, set focus to first 'focus-able' element in panel
if (theSlider.style.display!="none") {
var ctrls=theSlider.getElementsByTagName("*");
for (var c=0; c<ctrls.length; c++) {
var t=ctrls[c].tagName.toLowerCase();
if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
{ try{ ctrls[c].focus(); } catch(err){;} break; }
}
}
var cookie=theTarget.sliderCookie;
if (cookie && cookie.length) {
config.options[cookie]=!isOpen;
if (config.options[cookie]!=theTarget.defOpen) window.saveOptionCookie(cookie);
else window.removeCookie(cookie); // remove cookie if slider is in default display state
}
// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
// prevent clicks *within* a slider button from being processed by browser
// but allow plain click to bubble up to page background (to close transients, if any)
if (e.shiftKey || theTarget!=resolveTarget(e))
{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
Popup.remove(); // close open popup (if any)
return false;
}
//}}}
//{{{
// click in document background closes transient panels
document.nestedSliders_savedOnClick=document.onclick;
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);
if (document.nestedSliders_savedOnClick)
var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
// if click was inside a popup... leave transient panels alone
var p=target; while (p) if (hasClass(p,"popup")) break; else p=p.parentNode;
if (p) return retval;
// if click was inside transient panel (or something contained by a transient panel), leave it alone
var p=target; while (p) {
if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
p=p.parentNode;
}
if (p) return retval;
// otherwise, find and close all transient panels...
var all=document.all?document.all:document.getElementsByTagName("DIV");
for (var i=0; i<all.length; i++) {
// if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
// otherwise, if the panel is currently visible, close it by clicking it's button
if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button})
if (!hasClass(all[i],"floatingPanel")&&!hasClass(all[i],"sliderPanel")) all[i].style.display="none";
}
return retval;
};
//}}}
//{{{
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
if (hasClass(panel,"floatingPanel") && !hasClass(panel,"undocked")) {
// see [[MoveablePanelPlugin]] for use of 'undocked'
var rightEdge=document.body.offsetWidth-1;
var panelWidth=panel.offsetWidth;
var left=0;
var top=btn.offsetHeight;
if (place.style.position=="relative" && findPosX(btn)+panelWidth>rightEdge) {
left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
if (findPosX(btn)+left<0) left=-findPosX(btn); // stay within left edge
}
if (place.style.position!="relative") {
var left=findPosX(btn);
var top=findPosY(btn)+btn.offsetHeight;
var p=place; while (p && !hasClass(p,'floatingPanel')) p=p.parentNode;
if (p) { left-=findPosX(p); top-=findPosY(p); }
if (left+panelWidth>rightEdge) left=rightEdge-panelWidth;
if (left<0) left=0;
}
panel.style.left=left+"px"; panel.style.top=top+"px";
}
}
//}}}
//{{{
// TW2.1 and earlier:
// hijack Slider stop handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }
// TW2.2+
// hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
Morpher.prototype.coreStop = Morpher.prototype.stop;
Morpher.prototype.stop = function() {
this.coreStop.apply(this,arguments);
var e=this.element;
if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
// adjust panel overflow and position after animation
e.style.overflow = "visible";
if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
}
};
}
//}}}
/***
|Name|NestedSlidersPluginInfo|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.4.9|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for NestedSlidersPlugin|
This plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content.
!!!!!Usage
<<<
Use {{{+++}}} and {{{===}}} to delimit the slider content. You can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created. This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.
Additional optional syntax elements let you specify
*default to open
*cookiename
*heading level
*floater (with optional CSS width value)
*transient display (clicking elsewhere closes panel)
*open on hover (without needing to click)
*custom class/label/tooltip/accesskey
*alternate label/tooltip (displayed when panel is open)
*panelID (for later use with {{{<<DOM>>}}} macro. See [[DOMTweaksPlugin]])
*automatic blockquote style on panel
*deferred rendering of panel content
The complete syntax, using all options, is:
//{{{
++++(cookiename)!!!!!^width^*@{{class{[label=key|tooltip][altlabel|alttooltip]}}}#panelID:>...
content goes here
===
//}}}
where:
* ''"""+++""" (or """++++""") and """==="""''<br>marks the start and end of the slider definition, respectively. When the extra {{{+}}} is used, the slider will be open when initially displayed.
* ''"""(cookiename)"""''<br>saves the slider opened/closed state, and restores this state whenever the slider is re-rendered.
* ''"""! through !!!!!"""''<br>displays the slider label using a formatted headline (Hn) style instead of a button/link style
* ''"""^width^ (or just ^)"""''<br>makes the slider 'float' on top of other content rather than shifting that content downward. 'width' must be a valid CSS value (e.g., "30em", "180px", "50%", etc.). If omitted, the default width is "auto" (i.e., fit to content)
* ''"""*"""''<br>denotes "transient display": when a click occurs elsewhere in the document, the slider/floating panel will be automatically closed. This is useful for creating 'pulldown menus' that automatically go away after they are used. //Note: using SHIFT-click on a slider label will open/close that slider without triggering the automatic closing of any transient slider panels that are currently displayed, permitting ''temporary'' display of several transient panels at once.//
* ''"""@"""''<br>denotes "open on hover": the slider/floating panel will be automatically opened as soon as the mouse moves over the slider label, without requiring a click.
* ''"""{{class{[label=key|tooltip][altlabel|alttooltip]}}}"""''<br>uses label/tooltip/accesskey. """{{class{...}}}""", """=key""", """|tooltip""" and """[altlabel|alttooltip]""" are optional. 'class' is any valid CSS class name, used to style the slider label text. 'key' must be a ''single letter only''. altlabel/alttooltip specify alternative label/tooltip for use when slider/floating panel is displayed. //Note: you can use HTML syntax within the label text to include HTML entities (e.g., {{{»}}} (») or {{{►}}} (►), or even embedded images (e.g., {{{<img src="images/eric3.gif">}}}).//
* ''"""#panelID:"""''<br>defines a unique DOM element ID that is assigned to the panel element used to display the slider content. This ID can then be used later to reposition the panel using the {{{<<DOM move id>>}}} macro (see [[DOMTweaksPlugin]]), or to access/modify the panel element through use of {{{document.getElementById(...)}}}) javascript code in a plugin or inline script.
* ''""">"""''<br>automatically adds blockquote formatting to slider content
* ''"""..."""''<br>defers rendering of closed sliders until the first time they are opened. //Note: deferred rendering may produce unexpected results in some cases. Use with care.//
//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//
<<<
!!!!!Examples
<<<
simple in-line slider:
{{{
+++
content
===
}}}
+++
content
===
----
use a custom label and tooltip:
{{{
+++[label|tooltip]
content
===
}}}
+++[label|tooltip]
content
===
----
content automatically blockquoted:
{{{
+++>
content
===
}}}
+++>
content
===
----
all options (except cookie) //(default open, heading, sized floater, transient, open on hover, class, label/tooltip/key, blockquoted, deferred)//
{{{
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}>...
content
===
}}}
++++!!!^30em^*@{{big{[label=Z|click or press Alt-Z to open]}}}>...
content
===
----
complex nesting example:
{{{
+++[get info...=I|click for information or press Alt-I]
put some general information here,
plus a floating panel with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could in turn contain a transient panel,
perhaps with a +++^25em^*[glossary definition]explaining technical terms===
===
===
}}}
+++[get info...=I|click for information or press Alt-I]
put some general information here,
plus a floating panel with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could in turn contain a transient panel,
perhaps with a +++^25em^*[glossary definition]explaining technical terms===
===
===
----
embedded image as slider button
{{{
+++[<img src=images/eric3.gif>|click me!]>
{{big{OUCH!}}}
===
}}}
+++[<img src=images/eric3.gif>|click me!]>
{{big{OUCH!}}}
===
<<<
!!!!!Revisions
<<<
2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class). In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
2008.11.13 - 2.4.8 in document.onclick(), if transient panel is not a sliderPanel or floatingPanel, hide it via CSS
2008.10.05 - 2.4.7 in onClickNestedSlider(), added try/catch around focus() call to prevent IE error if input field being focused on is currently not visible.
2008.09.07 - 2.4.6 added removeCookie() function for compatibility with [[CookieManagerPlugin]]
2008.06.07 - 2.4.5 in 'onmouseover' handler for 'open on hover' slider buttons, use call() method when invoking document.onclick function (avoids error in IE)
2008.06.07 - 2.4.4 changed default for chkFloatingSlidersAnimate to FALSE to avoid clipping problem on some browsers (IE). Updated Morpher hijack (again) to adjust regular sliderPanel styles as well as floatingPanel styles.
2008.05.07 - 2.4.3 updated Morpher hijack to adjust floatingPanel styles after animation without affecting other animated elements (i.e. popups). Also, updated adjustSliderPos() to account for scrollwidth and use core findWindowWidth().
2008.04.02 - 2.4.2 in onClickNestedSlider, handle clicks on elements contained //within// slider buttons (e.g., when using HTML to display an image as a slider button).
2008.04.01 - 2.4.1 open on hover also triggers document.onclick to close other transient sliders
2008.04.01 - 2.4.0 re-introduced 'open on hover' feature using "@" symbol
2008.03.26 - 2.3.5 in document.onclick(), if click is in popup, don't dismiss transient panel (if any)
2008.01.08 - [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 - 2.3.4 added hijack for Animator.prototype.startAnimating(). Previously, the plugin code simply set the overflow to "visible" after animation. This code tweak corrects handling of elements that were styled with overflow=hidden/auto/scroll before animation by saving the overflow style and then restoring it after animation has completed.
2007.12.17 - 2.3.3 use hasClass() instead of direct comparison to test for "floatingPanel" class. Allows floating panels to have additional classes assigned to them (i.e., by AnimationEffectsPlugin).
2007.11.14 - 2.3.2 in onClickNestedSlider(), prevent SHIFT-click events from opening a new, empty browser window by setting "cancelBubble=true" and calling "stopPropagation()". Note: SHIFT-click is still processed as a normal click (i.e., it toggles the slider panel display). Also, using SHIFT-click will prevent 'transient' sliders from being automatically closed when another slider is opened, allowing you to *temporarily* display several transient sliders at once.
2007.07.26 - 2.3.1 in document.onclick(), propagate return value from hijacked core click handler to consume OR bubble up click as needed. Fixes "IE click disease", whereby nearly every mouse click causes a page transition.
2007.07.20 - 2.3.0 added syntax for setting panel ID (#panelID:). This allows individual slider panels to be repositioned within tiddler content simply by giving them a unique ID and then moving them to the desired location using the {{{<<DOM move id>>}}} macro.
2007.07.19 - 2.2.0 added syntax for alttext and alttip (button label and tooltip to be displayed when panel is open)
2007.07.14 - 2.1.2 corrected use of 'transient' attribute in IE to prevent (non-recursive) infinite loop
2007.07.12 - 2.1.0 replaced use of "*" for 'open/close on rollover' (which didn't work too well). "*" now indicates 'transient' panels that are automatically closed if a click occurs somewhere else in the document. This permits use of nested sliders to create nested "pulldown menus" that automatically disappear after interaction with them has been completed. Also, in onClickNestedSlider(), use "theTarget.sliderCookie", instead of "this.sliderCookie" to correct cookie state tracking when automatically dismissing transient panels.
2007.06.10 - 2.0.5 add check to ensure that window.adjustSliderPanel() is defined before calling it (prevents error on shutdown when mouse event handlers are still defined)
2007.05.31 - 2.0.4 add handling to invoke adjustSliderPanel() for onmouseover events on slider button and panel. This allows the panel position to be re-synced when the button position shifts due to changes in unrelated content above it on the page. (thanks to Harsha for bug report)
2007.03.30 - 2.0.3 added chkFloatingSlidersAnimate (default to FALSE), so that slider animation can be disabled independent of the overall document animation setting (avoids strange rendering and focus problems in floating panels)
2007.03.01 - 2.0.2 for TW2.2+, hijack Morpher.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
2007.03.01 - 2.0.1 in hijack for Slider.prototype.stop, use apply() to pass params to core function
2006.07.28 - 2.0.0 added custom class syntax around label/tip/key syntax: {{{{{classname{[label=key|tip]}}}}}}
2006.07.25 - 1.9.3 when parsing slider, save default open/closed state in button element, then in onClickNestedSlider(), if slider state matches saved default, instead of saving cookie, delete it. Significantly reduces the 'cookie overhead' when default slider states are used.
2006.06.29 - 1.9.2 in onClickNestedSlider(), when setting focus to first control, skip over type="hidden"
2006.06.22 - 1.9.1 added panel.defaultPanelWidth to save requested panel width, even after resizing has changed the style value
2006.05.11 - 1.9.0 added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label
2006.05.09 - 1.8.0 in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element
2006.04.24 - 1.7.8 in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position
2006.02.16 - 1.7.7 corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie
2006.02.15 - 1.7.6 in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)
2006.02.04 - 1.7.5 add 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals
2006.01.18 - 1.7.4 only define adjustSliderPos() function if it has not already been provided by another plugin. This lets other plugins 'hijack' the function even when they are loaded first.
2006.01.16 - 1.7.3 added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels. While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels. Short-term workaround is to only adjust the position for 'top-level' floaters.
2006.01.16 - 1.7.2 added button property to slider panel elements so that slider panel can tell which button it belongs to. Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
2006.01.14 - 1.7.1 added optional "^" syntax for floating panels. Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.
2006.01.14 - 1.7.0 added optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)
2006.01.03 - 1.6.2 When using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element. (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)
2005.12.15 - 1.6.1 added optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders
removed checkbox option for 'global' application of lazy sliders
2005.11.25 - 1.6.0 added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)
2005.11.21 - 1.5.1 revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability. Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.
2005.11.20 - 1.5.0 added (cookiename) syntax for optional tracking and restoring of slider open/close state
2005.11.11 - 1.4.0 added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style
2005.11.07 - 1.3.0 removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines
2005.11.05 - 1.2.1 changed name to NestedSlidersPlugin
2005.11.04 - 1.2.0 added alternative character-mode syntax {{{(((}}} and {{{)))}}}
tweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax
2005.11.03 - 1.1.1 fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used. code cleanup, added documentation
2005.11.03 - 1.1.0 changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}. changed name to EasySlidersPlugin
2005.11.03 - 1.0.0 initial public release
<<<
/% {{ "$1" != "$" + "1" ? "$1" : "Open links in %0"}}
computed param when called as: <<tiddler OpenStoryButton with: "button label" "tooltip" > >
$1 is set to "button label" and $2 is set to "tooltip" if no params are specified, $1 and $2 are
not substituted. So the computed param checks to see if $1 was replaced (by concatenating
$ and 1 so I don't have the obviously false "$1" != "$1") and if it was uses it. If it wasn't use
the alternate string with %1 being the name of the parent tiddler.
No return after the % and / so no newline is rendered when included.
%/{{openStoryButton{
<<openStory {{tiddler.title}} {{ "$1" != "$" + "1" ? "$1" : "Open links in %0"}} {{ "$2" != "$" + "2" ? "$2" : "Open all of the links in %0 according to the check boxes"}}>>
''The first/topmost checked box determines how tidders are opened''
<<option chkStoryClose>> close other tiddlers when opening
<<option chkStoryBottom>> open tiddlers at bottom of story column
<<option chkStoryTop>> open tiddlers at top of story column
}}}
Verticals are the name supplied to TiddlyWiki used for a specific task.
<html>
<hide linebreaks>
<ul>
<li>Educational Coursebook - Textbook, presentations and note taking all in one</li>
<li class="overlay2">TWAB - http://www.tiddly-twab.com/ - ~TiddlyWIki Address Book</li>
<li class="overlay3">~MediaWiki unplugged - http://mediawikiunplugged.com/ - take your mediawiki with you</li>
<li class="overlay4">Team Tasks - http://getteamtasks.com/ -- a task management tool
<li class="overlay5">~NoteStorm - http://www.giffmex.org/NoteStorm.html -- an astonishingly simple way to take and organize notes
</ul>
</html>
{{overlay5{See more at the non-profit company that supports TiddlyWiki: http://www.osmosoft.com/#Products}}}
! Toolbar command for tiddlers tagged with content.
|~ContentViewToolbar|closeTiddler closeOthers editTiddler refresh jump > fields permalink references < |
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<span style='display:none' macro='tiddler SiteStartup'></span>
<!--}}}-->
/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts.
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features"). E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.
''Syntax:''
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <br />If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any tiddler content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.
Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations".
Wrap every citation with a part and a proper name.
''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.//
in //Proc. ICSM//, 1998.</part>
<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.//
Thesis, Uni Stuttgart, 2002.</part>
<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.//
in //Proc. ICSM//, 1999.</part>
}}}
You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.
Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.
''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|
<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}
Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".
BTW: The same approach can be used to create bullet lists with items that contain more than one line.
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.
With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.
''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline
Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab
Timeline Timeline SideBarTabs/Timeline
All 'All tiddlers' SideBarTabs/All
Tags 'All tags' SideBarTabs/Tags
More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab
Missing 'Missing tiddlers' SideBarTabs/Missing
Orphans 'Orphaned tiddlers' SideBarTabs/Orphans
Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}
Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.
E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler
sortBy 'tiddler.modified' descending
write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature
''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}
Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!Code<html><a name="Code"/></html>
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
***/
//{{{
//============================================================================
// PartTiddlerPlugin
// Ensure that the PartTiddler Plugin is only installed once.
//
if (!version.extensions.PartTiddlerPlugin) {
version.extensions.PartTiddlerPlugin = {
major: 1, minor: 0, revision: 9,
date: new Date(2007, 6, 14),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"
};
if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");
//============================================================================
// Common Helpers
// Looks for the next newline, starting at the index-th char of text.
//
// If there are only whitespaces between index and the newline
// the index behind the newline is returned,
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
var re = /(\n|[^\s])/g;
re.lastIndex = index;
var result = re.exec(text);
return (result && text.charAt(result.index) == '\n')
? result.index+1
: index;
}
//============================================================================
// Constants
var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";
//============================================================================
// Plugin Specific Helpers
// Parse the parameters inside a <part ...> tag and return the result.
//
// @return [may be null] {partName: ..., isHidden: ...}
//
var parseStartTagParams = function(paramText) {
var params = paramText.readMacroParams();
if (params.length == 0 || params[0].length == 0) return null;
var name = params[0];
var paramsIndex = 1;
var hidden = false;
if (paramsIndex < params.length) {
hidden = params[paramsIndex] == "hidden";
paramsIndex++;
}
return {
partName: name,
isHidden: hidden
};
}
// Returns the match to the next (end or start) part tag in the text,
// starting the search at startIndex.
//
// When no such tag is found null is returned, otherwise a "Match" is returned:
// [0]: full match
// [1]: matched "end" tag (or null when no end tag match)
// [2]: matched "start" tag (or null when no start tag match)
// [3]: content of start tag (or null if no start tag match)
//
var findNextPartEndOrStartTagMatch = function(text, startIndex) {
var re = new RegExp(partEndOrStartTagRE);
re.lastIndex = startIndex;
var match = re.exec(text);
return match;
}
//============================================================================
// Formatter
// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.
//
// @return true if a complete part section (including the end tag) could be processed, false otherwise.
//
var handlePartSection = function(w) {
var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);
if (!tagMatch) return false;
if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;
// Parse the start tag parameters
var arguments = parseStartTagParams(tagMatch[3]);
if (!arguments) return false;
// Continue processing
var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);
var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);
if (endMatch && endMatch[1]) {
if (!arguments.isHidden) {
w.nextMatch = startTagEndIndex;
w.subWikify(w.output,partEndTagREString);
}
w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);
return true;
}
return false;
}
config.formatters.push( {
name: "part",
match: "<part\\s+[^>]+>",
handler: function(w) {
if (!handlePartSection(w)) {
w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);
}
}
} )
//============================================================================
// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers
// as tiddlers.
var currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)
// Return the match to the first <part ...> tag of the text that has the
// requrest partName.
//
// @return [may be null]
//
var findPartStartTagByName = function(text, partName) {
var i = 0;
while (true) {
var tagMatch = findNextPartEndOrStartTagMatch(text, i);
if (!tagMatch) return null;
if (tagMatch[2]) {
// Is start tag
// Check the name
var arguments = parseStartTagParams(tagMatch[3]);
if (arguments && arguments.partName == partName) {
return tagMatch;
}
}
i = tagMatch.index+tagMatch[0].length;
}
}
// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler
// object, using fullName as the Tiddler's title.
//
// All remaining properties of the new Tiddler (tags etc.) are inherited from
// the parentTiddler.
//
// @return [may be null]
//
var getPart = function(parentTiddler, partName, fullName) {
var text = parentTiddler.text;
var startTag = findPartStartTagByName(text, partName);
if (!startTag) return null;
var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);
var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);
if (indexOfEndTag >= 0) {
var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);
var partTiddler = new Tiddler();
partTiddler.set(
fullName,
partTiddlerText,
parentTiddler.modifier,
parentTiddler.modified,
parentTiddler.tags,
parentTiddler.created);
partTiddler.abegoIsPartTiddler = true;
return partTiddler;
}
return null;
}
// Hijack the store.fetchTiddler to recognize the "part" addresses.
//
var hijackFetchTiddler = function() {
var oldFetchTiddler = store.fetchTiddler ;
store.fetchTiddler = function(title) {
var result = oldFetchTiddler.apply(this, arguments);
if (!result && title) {
var i = title.lastIndexOf('/');
if (i > 0) {
var parentName = title.substring(0, i);
var partName = title.substring(i+1);
var parent = (parentName == ".")
? store.resolveTiddler(currentParent)
: oldFetchTiddler.apply(this, [parentName]);
if (parent) {
return getPart(parent, partName, parent.title+"/"+partName);
}
}
}
return result;
};
};
// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag.
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
var oldRestartFunc = restart;
window.restart = function() {
hijackFetchTiddler();
oldRestartFunc.apply(this,arguments);
};
} else
hijackFetchTiddler();
// The user must not edit a readOnly/partTiddler
//
config.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;
Tiddler.prototype.isReadOnly = function() {
// Tiddler.isReadOnly was introduced with TW 2.0.6.
// For older version we explicitly check the global readOnly flag
if (config.commands.editTiddler.oldIsReadOnlyFunction) {
if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;
} else {
if (readOnly) return true;
}
return this.abegoIsPartTiddler;
}
config.commands.editTiddler.handler = function(event,src,title)
{
var t = store.getTiddler(title);
// Edit the tiddler if it either is not a tiddler (but a shadowTiddler)
// or the tiddler is not readOnly
if(!t || !t.abegoIsPartTiddler)
{
clearMessage();
story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
story.focusTiddler(title,"text");
return false;
}
}
// To allow the "./partName" syntax in macros we need to hijack
// the invokeMacro to define the "currentParent" while it is running.
//
var oldInvokeMacro = window.invokeMacro;
function myInvokeMacro(place,macro,params,wikifier,tiddler) {
var oldCurrentParent = currentParent;
if (tiddler) currentParent = tiddler;
try {
oldInvokeMacro.apply(this, arguments);
} finally {
currentParent = oldCurrentParent;
}
}
window.invokeMacro = myInvokeMacro;
// To correctly support the "./partName" syntax while refreshing we need to hijack
// the config.refreshers.tiddlers to define the "currentParent" while it is running.
//
(function() {
var oldTiddlerRefresher= config.refreshers.tiddler;
config.refreshers.tiddler = function(e,changeList) {
var oldCurrentParent = currentParent;
try {
currentParent = e.getAttribute("tiddler");
return oldTiddlerRefresher.apply(this,arguments);
} finally {
currentParent = oldCurrentParent;
}
};
})();
// Support "./partName" syntax inside <<tabs ...>> macro
(function() {
var extendRelativeNames = function(e, title) {
var nodes = e.getElementsByTagName("a");
for(var i=0; i<nodes.length; i++) {
var node = nodes[i];
var s = node.getAttribute("content");
if (s && s.indexOf("./") == 0)
node.setAttribute("content",title+s.substr(1));
}
};
var oldHandler = config.macros.tabs.handler;
config.macros.tabs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var result = oldHandler.apply(this,arguments);
if (tiddler)
extendRelativeNames(place, tiddler.title);
return result;
};
})();
// Scroll the anchor anchorName in the viewer of the given tiddler visible.
// When no tiddler is defined use the tiddler of the target given event is used.
window.scrollAnchorVisible = function(anchorName, tiddler, evt) {
var tiddlerElem = null;
if (tiddler) {
tiddlerElem = document.getElementById(story.idPrefix + tiddler);
}
if (!tiddlerElem && evt) {
var target = resolveTarget(evt);
tiddlerElem = story.findContainingTiddler(target);
}
if (!tiddlerElem) return;
var children = tiddlerElem.getElementsByTagName("a");
for (var i = 0; i < children.length; i++) {
var child = children[i];
var name = child.getAttribute("name");
if (name == anchorName) {
var y = findPosY(child);
window.scrollTo(0,y);
return;
}
}
}
} // of "install only once"
//}}}
/***
<html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2006 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
<html><sub><a href="javascript:;" onclick="scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>
***/
{{nocol{}}}
This describes the changes made to the plugins that are tagged with PatchedPlugin. These plugins should not be redistributed outside of the coursebook. The following plugins have been patched:
{{sectionTOC{}}}
! AnnotationsPlugin
Fixed usage comments from:
{{{
((text to annotate(annotation goes here)
}}}
to
{{{
((text to annotate(annotation goes here)))
}}}
in both places.
! FootnotesPlugin
Fix for issues when rendered as part of saving rss feed. It tries to add itself to the containing tiddler as though it was being rendered in the story column. But for RSS there is no story and it errors. Added:
{{{
if (!story.findContainingTiddler(place)) return;
}}}
at the top of the handler function.
Also fixed a mising check to see if tiddler was defined:
{{{
Story.prototype.refreshTiddler = function(title,template,force)
{
var tiddler = old_footnotes_refreshTiddler.apply(this,arguments);
if (tiddler && tiddler.notes && tiddler.notes.length)
{ ...
}}}
prepended the "{{{tiddler &&}}}" to the if statement in case the refresh returns null (was causing an error in IE 7).
! PartTiddlerPlugin
Change {{{<<br>>}}} to {{{<br />}}}.
! QuizzerPlugin
Added {{{return false;}}} at the end of checkOut to prevent IE from alerting about leaving the web page.
! SyncFromSourcePlugin
change ~FileAdaptor.minHostName to ~AdaptorBase.minHostName to get it to work with newer tiddlywikis.
!TableSortingPlugin
From: http://groups.google.com/group/TiddlyWiki/browse_thread/thread/cced75d513e00a21
{{{
The fix is to use a more precise conditional by changing these two
lines:
if(!x && hasClass(h,"autosort")) {
if(x)
to:
if(x===null && hasClass(h,"autosort")) {
if(x!==null)
That should do it.
}}}
! TiddlerNotesPlugin
From discussion in:
http://groups.google.com/group/TiddlyWiki/browse_thread/thread/c70af7be67524685/770b706c64529caa?#770b706c64529caa
Well guess I answered my own question. I started firebug and reloaded the tw. Then I switched to the script tab and enabled "break on all errors". Then I opened the import tab, switched to web and clicked on select a server and that resulted in:
{{{
77 if(attribs){
78 for(var n in attribs){
79 e.setAttribute(n,attribs[n]);
80 }
81 }
}}}
the error it reports is:
{{{
e is not defined
}}}
this code is inside the function:
{{{
function createTiddlyButton
(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey,attribs)
}}}
Looking at the function: {{{function createTiddlyElement (theParent,theElement,theID,theClass,theText,attribs)}}}
it uses the variable e in a similar way, however in createTiddlyButton the variable is:
{{{
var theButton = document.createElement("a");
}}}
could it be that e.setAttribute should be theButton.setAttribute?
Yes it should be.
!! Enhancement to allow printing of notes without empty notes blocks
When printing the story column, the notes block were taking up a lot of room and if they were empty, they were just wasted space.
I could turn off printing of the notes block, but I wanted to print them if the notes blocks had content. I patched the TiddlerNotesPlugin
to add the class ~TiddlerNotesExists to the notes blocks where there is a notes tiddler (indicating useful information). The patch replaced:
{{{
var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes",null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
}}}
in the notes handler with:
{{{
// rouilj add a class for notes that have contents in a tiddler.
var notesTiddlerExists = store.tiddlerExists(tiddler.title+"-"+suffix);
var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes" + (notesTiddlerExists?" TiddlerNotesExists":""),null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
}}}
note the space between the " and ~TiddlerNotesExists. It must be there so that ~TiddlerNotes has a space after it otherwise the class names aren't correct.
Then the stylesheet was changed to not display the class ~TiddlerNotes but to display ~TiddlerNotesExists when printing. Also the edit notes button was hidden for printing.
! TiddlyLockPlugin
In top documentation table in the Overrides section, replaced obsolete {{{<<br>>}}} macro with {{{<br />}}}.
Also doesn't work under safari. Notify the user and bypass it's lock.
<<sectionTOC>>
[[What is plod?]]
[[What are the enhancements?]]
[[Using plod]]
[[Reporting from plod]]
[[Searching plod]]
[[Demo]]
Intro to the coursebook and {{exclude{tiddlywiki}}} in general
[[Slide Welcome]]
[[What is a TiddlyWiki]]
[[Coursebook Orientation]]
The parts of this coursebook:
* Chapters
* Presentations (shows)
* Quizzes
[[Tiddler Types in This Coursebook]]
[[Course Structure]]
[[Using Notebook]]
[[Using Shows]]
[[Using Chapters]]
/%use sort order to override default title based ordering. Anything with an explicit order will be sorted before the title sorted section.%/ {{adiv{<<showWhenExists InstructorSlideShowStyleSheet>><<matchTags inline {{'* <<slideShow noClicks tiddler:%0 label:%0 clock:-15 theme:InstructorSlideShowStyleSheet toc:titles >' + '> @@font-size:smaller;%0@@'}} "\n" sort:title Presentation>>}}}{{adiv{<<hideWhenExists InstructorSlideShowStyleSheet>><<matchTags inline {{'* <<slideShow noKeyboard noClicks noOverlays tiddler:%0 label:%0 toc:titles >' + '>'}} "\n" sort:title Presentation>>}}}
<!--{{{-->
<div class='toolbar' macro='toolbar [[OtherToolbarCommands::ContentViewToolbar]]'></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='showWhenExists InstructorSlideShowStyleSheet'>
<div macro='tiddler SlideStyleLinks##Instructor'></div>
<div macro='slideShow theme:InstructorSlideShowStyleSheet toc:titles noClicks footer:"copyright© 2009<br />John Rouillard" clock:+ label:"Instructor" tooltip:"Start slideshow in instructor projection mode"'></div>
</div>
<div macro='tiddler SlideStyleLinks##Student'></div>
<div class='viewer' macro='slideShow noClicks noKeyboard noOverlays toc:titles label:"Student" tooltip:"Start the slideshow in student mode"'></div>
<div macro='tiddler SlideStyleLinks##Print'></div>
<div class='viewer' macro='slideShow showAll theme:PrintingSlideShowStyleSheet label:Print tooltip:"Display slide show for printing"'></div>
<hr />
</div>
<div class='viewer' macro='view text wikified'></div>
<span macro="sectionTOC"></span>
<div id="Notes" class='notes viewer' macro='notes heading:Notebook tag:"Notes excludeLists noReload" suffix:Notes'></div>
<div class='tagClear'></div>
<!--}}}-->
/*{{{*/
/* Default style sheet settings for printing */
#contentWrapper.slideShowMode #displayArea{
font-size: 150%;
margin: 1em 15.5em 0em 1em !important;
}
h1,h2,h3 {margin-top:0.3em}
.slideFooterOff #navigator{
display: none;
}
#controlBar{
display: none;
}
@media print {
.tiddler{
page-break-after: always;
border: 2px solid blue;
margin: 1em 0 1em 0;
padding: 0.5em
}
.viewer pre { background-color: transparent; }
#contentWrapper.slideShowMode .comment{
background-color: transparent;
}
}
.notes {
display: none;
}
.comment{
border: 1pt dashed;
padding: 0.5em;
}
#contentWrapper.slideShowMode #displayArea {margin: 1em 0em 0em 0em !important;}
}
/*}}}*/
<<matchTags inline "* %0" "\n" sort:title quiz>> @@display:none; use sort order to override default title based ordering. Anything with an explicit order will be sorted before the title sorted section. @@
/***
|''Name:''|QuizzerPlugin|
|''Description:''|Makes quizzes with optional grades|
|''Version:''|1.0.2|
|''Date:''|Nov 11, 2008|
|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|
|''Documentation:''|[[QuizzerPlugin Documentation|QuizzerPluginDoc]]|
|''Author:''|Paulo Soares|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.1.0|
***/
//{{{
config.macros.quiz = {
wrongAnswer: "Incorrect answer. Please think again.",
rightAnswer: "That's right!",
trueValue: "True",
falseValue: "False",
handler: function(place,macroName,params,wikifier,paramString){
var par = paramString.parseParams("list",null,true);
var type = getParam(par,"type","M");
var panelType = (type.length>1) ? type.charAt(1) : "";
type = type.charAt(0);
var id = getParam(par,"id","");
if(id=="" && type!="M") return; // not sure about this
var value = getParam(par,"value",false);
var tiddler = getParam(par,"tiddler","");
var score = parseFloat(getParam(par,"score",0));
var toolTip = "";
if(type=="T"){
toolTip = this.trueValue;
if(value==false){
var tempTiddler=tiddler;
tiddler="";
var tempScore=score;
score=0;
}
}
this.createAnswer(place, type, toolTip, true, panelType, tiddler, value, score, id);
if(type=="T"){
tiddler=(value==false)?tempTiddler:"";
score=(value==false)?tempScore:0;
toolTip = this.falseValue;
this.createAnswer(place, type, toolTip, false, panelType, tiddler, !value, score, id);
}
},
createAnswer: function(place, type, toolTip, correction, panelType, tiddler, value, score, id){
var checked=false;
if(correction){
var correct = createTiddlyElement(place,"span","","correction","");
correct.style.display='none';
correct.style.fontWeight='bold';
checked=true;
}
if(type=="M"){
var btn = createTiddlyCheckbox(place,"",false,this.onClickAnswer);
} else {
var btn = createTiddlyRadiobox(place,"",checked,this.onClickAnswer,id);
}
btn.className = "answerItem";
btn.value=score;
if(toolTip!="") btn.title=toolTip;
var panelClass = (panelType=="=") ? "sliderPanel" : "floatingPanel"; //default to floating
var text = (tiddler!="") ? store.getTiddlerText(tiddler) : "";
if(text==""){text = (value) ? this.rightAnswer : this.wrongAnswer;}
var panel = createTiddlyElement(null,"div","",panelClass);
panel.style.display = "none"; //default to closed
panel.onclick=function(){this.style.display="none";};
place.appendChild(panel);
wikify(text,panel,null);
},
onClickAnswer: function(e){
if(!e) var e = window.event;
var panel = this.nextSibling;
if(this.checked){
var validated = 1;
var visiblePanel=document.getElementById('visiblePanel');
var sC = Story.prototype.findContainingTiddler(this).id.substr(7)+'_scoreCard';
var scoreCard=document.getElementById(sC);
if(visiblePanel){
visiblePanel.style.display="none";
visiblePanel.id="";
}
if(scoreCard){validated = scoreCard.value;}
if(validated==1){
panel.style.display = "block";
panel.id="visiblePanel";
var left= e.clientX +10;
panel.style.left = left + "px";
}
} else {
panel.style.display = "none";
panel.id="";
}
}
};
config.macros.score= {
trueSymbol: "✔",
falseSymbol: "✘",
label: "Score »",
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var btn = createTiddlyButton(place,this.label,"",this.checkOut);
btn.id=tiddler.title+"_scoreCard";
btn.value=0;
},
checkOut: function(e){
if(this.value==1) return;
var total=score=points=0;
var answers=getElementsByClass("answerItem",document.getElementById('viewer'));
var answersLen=answers.length;
for(var i=0; i<answersLen; i++) {
points=parseFloat(answers[i].value);
score+=answers[i].checked*points;
if(points>0)total+=points;
var correct=answers[i].previousSibling;
if(correct.className=="correction"){
if(answers[i].checked == (points>0)){
correct.firstChild.data=config.macros.score.trueSymbol;
correct.style.color = '#0f0';
} else {
correct.firstChild.data=config.macros.score.falseSymbol;
correct.style.color = '#f00';
}
correct.style.display='inline';
}
}
var text = " " + score+"/"+total;
createTiddlyElement(this,"span","","",text);
this.value=1;
return false;
}
};
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null ) node = document;
if ( tag == null ) tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (var i = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {classElements.push(els[i]);}
}
return classElements;
}
function createTiddlyRadiobox(theParent,caption,checked,onChange,id){
var cb = document.createElement("input");
cb.type = "radio";
cb.name = id;
cb.onclick = onChange;
theParent.appendChild(cb);
cb.checked = checked;
cb.className = "chkOptionInput";
if(caption) wikify(caption,theParent);
return cb;
}
setStylesheet("/*{{{*/\n.floatingPanel {\n color: black;\n;position: absolute;\nz-index: 10;\npadding: 0.5em;\nbackground-color: #eee;\nborder: 1px solid #333;\ncursor: crosshair}\n\n.sliderPanel {padding: 0.5em;\nborder: 1px dotted #333;\nwidth: auto;\ncursor: crosshair}\n\n/*}}}*/","AnswerPanelStyles");
config.shadowTiddlers.QuizzerPluginDoc="The documentation is missing. It is available [[here|http://www.math.ist.utl.pt/~psoares/addons.html#QuizzerPluginDoc]].";
//}}}
!!!!Syntax
The QuizzerPlugin has five parameters; most are optional:
//{{{
<<quiz [type:type[=]] [id:id] [tiddler:tiddler] [value:value] [score:score]>>
//}}}
Parameters:
*type (string)
**"M" (multiple answer checkbox) (default)
**"S" (single-answer radio button group)
**"T" (true/false question)
***append "=" for sliding panel (e.g., T=, S=, M=)
*id (string)
**required for types S and T only
***for type S value must be unique across a group of questions
***for type T value must be unique for each question
*tiddler (string, //optional//)
**display text from tiddler in the panel
**default is config.macros.answer.wrongAnswer or config.macros.answer.rightAnswer according to the value of the next parameter
*value
**use {{{value:true}}} to indicate that the true answer is right
**should be omitted otherwise
*score (number)
**sets the score for an answer
** default is 0
/***
|''Name:''|RSSReaderPlugin|
|''Description:''|This plugin provides a RSSReader for TiddlyWiki|
|''Version:''|1.1.2|
|''Date:''|2008-09-02|
|''Source:''|http://tiddlywiki.bidix.info/#RSSReaderPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#RSSReaderPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''Credit:''|BramChen for RssNewsMacro|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''OptionalRequires:''|http://www.tiddlytools.com/#NestedSlidersPlugin|
***/
//{{{
version.extensions.RSSReaderPlugin = {
major: 1, minor: 1, revision: 2,
date: new Date("2008-09-02"),
source: "http://TiddlyWiki.bidix.info/#RSSReaderPlugin",
author: "BidiX",
coreVersion: '2.2.0'
};
config.macros.rssReader = {
dateFormat: "DDD, DD MMM YYYY",
itemStyle: "display: block;border: 1px solid black;padding: 5px;margin: 5px;", //useed '@@'+itemStyle+itemText+'@@'
msg:{
permissionDenied: "Permission to read preferences was denied.",
noRSSFeed: "No RSS Feed at this address %0",
urlNotAccessible: " Access to %0 is not allowed"
},
cache: [], // url => XMLHttpRequest.responseXML
desc: "noDesc",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var desc = params[0];
var feedURL = params[1];
var toFilter = (params[2] ? true : false);
var filterString = (toFilter?(params[2].substr(0,1) == ' '? tiddler.title:params[2]):'');
var place = createTiddlyElement(place, "div", "RSSReader");
wikify("^^<<rssFeedUpdate "+feedURL+" [[" + tiddler.title + "]]>>^^\n",place);
if (this.cache[feedURL]) {
this.displayRssFeed(this.cache[feedURL], feedURL, place, desc, toFilter, filterString);
}
else {
var r = loadRemoteFile(feedURL,config.macros.rssReader.processResponse, [place, desc, toFilter, filterString]);
if (typeof r == "string")
displayMessage(r);
}
},
// callback for loadRemoteFile
// params : [place, desc, toFilter, filterString]
processResponse: function(status, params, responseText, url, xhr) { // feedURL, place, desc, toFilter, filterString) {
if (window.netscape){
try {
if (document.location.protocol.indexOf("http") == -1) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
}
}
catch (e) { displayMessage(e.description?e.description:e.toString()); }
}
if (xhr.status == 404)
{
displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
return;
}
if (!status)
{
displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
return;
}
if (xhr.responseXML) {
// response is interpreted as XML
config.macros.rssReader.cache[url] = xhr.responseXML;
config.macros.rssReader.displayRssFeed(xhr.responseXML, params[0], url, params[1], params[2], params[3]);
}
else {
if (responseText.substr(0,5) == "<?xml") {
// response exists but not return as XML -> try to parse it
var dom = (new DOMParser()).parseFromString(responseText, "text/xml");
if (dom) {
// parsing successful so use it
config.macros.rssReader.cache[url] = dom;
config.macros.rssReader.displayRssFeed(dom, params[0], url, params[1], params[2], params[3]);
return;
}
}
// no XML display as html
wikify("<html>" + responseText + "</html>", params[0]);
displayMessage(config.macros.rssReader.msg.noRSSFeed.format([url]));
}
},
// explore down the DOM tree
displayRssFeed: function(xml, place, feedURL, desc, toFilter, filterString){
// Channel
var chanelNode = xml.getElementsByTagName('channel').item(0);
var chanelTitleElement = (chanelNode ? chanelNode.getElementsByTagName('title').item(0) : null);
var chanelTitle = "";
if ((chanelTitleElement) && (chanelTitleElement.firstChild))
chanelTitle = chanelTitleElement.firstChild.nodeValue;
var chanelLinkElement = (chanelNode ? chanelNode.getElementsByTagName('link').item(0) : null);
var chanelLink = "";
if (chanelLinkElement)
chanelLink = chanelLinkElement.firstChild.nodeValue;
var titleTxt = "!![["+chanelTitle+"|"+chanelLink+"]]\n";
var title = createTiddlyElement(place,"div",null,"ChanelTitle",null);
wikify(titleTxt,title);
// ItemList
var itemList = xml.getElementsByTagName('item');
var article = createTiddlyElement(place,"ul",null,null,null);
var lastDate;
var re;
if (toFilter)
re = new RegExp(filterString.escapeRegExp());
for (var i=0; i<itemList.length; i++){
var titleElm = itemList[i].getElementsByTagName('title').item(0);
var titleText = (titleElm ? titleElm.firstChild.nodeValue : '');
if (toFilter && ! titleText.match(re)) {
continue;
}
var descText = '';
descElem = itemList[i].getElementsByTagName('description').item(0);
if (descElem){
try{
for (var ii=0; ii<descElem.childNodes.length; ii++) {
descText += descElem.childNodes[ii].nodeValue;
}
}
catch(e){}
descText = descText.replace(/<br \/>/g,'\n');
if (desc == "asHtml")
descText = "<html>"+descText+"</html>";
}
var linkElm = itemList[i].getElementsByTagName("link").item(0);
var linkURL = linkElm.firstChild.nodeValue;
var pubElm = itemList[i].getElementsByTagName('pubDate').item(0);
var pubDate;
if (!pubElm) {
pubElm = itemList[i].getElementsByTagName('date').item(0); // for del.icio.us
if (pubElm) {
pubDate = pubElm.firstChild.nodeValue;
pubDate = this.formatDateString(this.dateFormat, pubDate);
}
else {
pubDate = '0';
}
}
else {
pubDate = (pubElm ? pubElm.firstChild.nodeValue : 0);
pubDate = this.formatDate(this.dateFormat, pubDate);
}
titleText = titleText.replace(/\[|\]/g,'');
var rssText = '*'+'[[' + titleText + '|' + linkURL + ']]' + '' ;
if ((desc != "noDesc") && descText){
rssText = rssText.replace(/\n/g,' ');
descText = '@@'+this.itemStyle+descText + '@@\n';
if (version.extensions.nestedSliders){
descText = '+++[...]' + descText + '===';
}
rssText = rssText + descText;
}
var story;
if ((lastDate != pubDate) && ( pubDate != '0')) {
story = createTiddlyElement(article,"li",null,"RSSItem",pubDate);
lastDate = pubDate;
}
else {
lastDate = pubDate;
}
story = createTiddlyElement(article,"div",null,"RSSItem",null);
wikify(rssText,story);
}
},
formatDate: function(template, date){
var dateString = new Date(date);
// template = template.replace(/hh|mm|ss/g,'');
return dateString.formatString(template);
},
formatDateString: function(template, date){
var dateString = new Date(date.substr(0,4), date.substr(5,2) - 1, date.substr(8,2)
);
return dateString.formatString(template);
}
};
config.macros.rssFeedUpdate = {
label: "Update",
prompt: "Clear the cache and redisplay this RssFeed",
handler: function(place,macroName,params) {
var feedURL = params[0];
var tiddlerTitle = params[1];
createTiddlyButton(place, this.label, this.prompt,
function () {
if (config.macros.rssReader.cache[feedURL]) {
config.macros.rssReader.cache[feedURL] = null;
}
story.refreshTiddler(tiddlerTitle,null, true);
return false;});
}
};
//}}}
//last update: RSSReaderPlugin v 1.1.1//
!Description
This plugin provides a RSSReader for TiddlyWiki
* It accesses asynchronously an RSSFeed
*Depending on the chanel item format, each item could be written as :
**simple text wikified
**html
!Usage
{{{
<<rssReader noDesc|asHtml|asText rssUrl ['filtering string']>>
noDesc: only title of item is printed
asHtml: if you know that description contain html (links, img ...),
the text is enclosed with <html> </html> tags
asText: if the description should not be interpreted as html the
description is wikified
rssUrl: the rssFeed url that could be accessed.
'filtering string': if present, the rssfeed item title must contained
this string to be displayed.
If 'filering string' contained space characters only, the tiddler
title is used for filtering.
}}}
For security reasons, if the TiddlyWiki is accessed from http, a ProxyService should be used to access an rssFeed from an other site.
!examples
| !reader | !RSSFeed type | !working from |
| BidiXTWRSS | Description asHtml | file: or tiddlywiki.bidix.info |
| [[Le Monde]] | Description asText | file: or tiddlywiki.bidix.info using proxy |
| YahooNewsSport | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| TiddlyWikiRSS | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| [[Libération]] | noDesc | file: or tiddlywiki.bidix.info using proxy |
| [[TestComment]] | asText and filters | file: or tiddlywiki.bidix.info using proxy |
see : <<tag RSSFeed>> for the full list.
!Revision history
* V1.1.0 (2207/04/13)
**No more import functions
* V1.0.0 (2006/11/11)
**refactoring using core loadRemoteFile function
**import using new tiddlywiki:tiddler element
**import and presentation preserved without EricShulman's NestedSliderPlugin
**better display of items
* v0.3.0 (24/08/2006)
** Filter on RSS item title
** Place to display redefined for asynchronous processing
* v0.2.2 (22/08/2006)
**Haloscan feed has no pubDate.
* v0.2.1 (08/05/2006)
* v0.2.0 (01/05/2006)
**Small adapations for del.icio.us feed
* v0.1.1 (28/04/2006)
**Bug : Channel without title
* v0.1.0 (24/04/2006)
** initial release
/***
|Macro|redirect (alias)|
|Author|[[Clint Checketts]] and Paul Petterson|
|Version|1.1 Jan 26, 2006|
|Location|http://checkettsweb.com/styles/themes.htm#RedirectMacro|
|Description|This macro tells TW to find all instances of a word and makes it point to a different link. For example, whenever I put the word 'Clint' in a tiddler I want TiddlyWiki to turn it into a link that points to a tiddler titled 'Clint Checketts' Or the word 'TW' could point to a tiddler called 'TiddlyWiki' It even matches clint (which is lowercase) [[Clint]] leet lEEt LEET|
|Usage|{{{<<redirect TW TiddlyWiki>>}}} |
|Example|<<redirect TW "TiddlyWiki">> <<redirect Clint "Clint Checketts">> (Nothing should appear, its just setting it all up)<<redirectExact lEEt Elite>>|
!Revisions
1.1- Fixed tiddler refresh so a tiddler declaring a redirect will also render the redirect
1.0- Updated to work with TiddlyWiki 2.0 (thanks to Udo Borkowski)
0.9- Original release October 2005
!Code
***/
//{{{
version.extensions.redirectExact = {major: 1, minor: 2, revision: 0, date: new Date(2005,10,24)};
config.macros.redirectExact = {label: "Pickles Rock!"};
config.macros.redirectExact.handler = function(place,macroName,params,wikifier,paramString,tiddler){
config.macros.redirect.handler(place,macroName,params,wikifier,paramString,tiddler);
}
version.extensions.redirect = {major: 1, minor: 2, revision: 0, date: new Date(2005,10,24)};
config.macros.redirect = {label: "Pickles Rock!"};
config.macros.redirect.handler = function(place,macroName,params,wikifier,paramString,tiddler){
var redirectExists = false
// Check to see if the wikifier exists
for (var i=0;i<config.formatters.length;i++)
if (config.formatters[i].name == "redirect"+params[0])
redirectExists = true;
//If it doesn't exist, add it!
if (!redirectExists){
for( var i=0; i<config.formatters.length; i++ )
if ( config.formatters[i].name=='wikiLink') break ;
if ( i >= config.formatters.length ) {
var e = "Can't find formatter for wikiLink!" ;
displayMessage( e ) ;
throw( e ) ;
}
var pattern;
if (macroName == 'redirect'){pattern=params[0].escapeRegExp().replace(/([A-Z])/img, function($1) {return("["+$1.toUpperCase()+$1.toLowerCase()+"]");});
} else {
pattern=params[0].escapeRegExp();
}
config.formatters.splice( i, 0, {
name: "redirect"+params[0],
match: "(?:\\b)(?:\\[\\[)?"+pattern+"(?:\\]\\])?(?:\\b)",
subst: params[1],
handler: function(w) {
var link = createTiddlyLink(w.output,this.subst,false);
w.outputText(link,w.matchStart,w.nextMatch);
}
});
formatter = new Formatter(config.formatters); //update the tiddler
if(tiddler) story.refreshTiddler(tiddler.title,null,true); //refresh tiddler so the new rule is applied
} // End if
}
//}}}
/***
***/
//{{{
config.commands.refresh = {
text: 'refresh',
tooltip: 'Refresh this tiddler',
handler: function(e,src,title) {
clearMessage();
story.refreshTiddler(title,false,true); // force=true
return false;
}
};
//}}}
{{{plod -T -d 12/01/2009 -D 12/08/2009}}}
{{overlay1{
{{{
Programming: 3:50
Programming:c 0:10
Programming:perl 3:40
TR: 0:30
TR:23 0:10
TR:32 0:20
zTOTAL = 4:20
}}}
}}}
/%
|Name|RescueStoreAreaCommand|
|Source|http://www.TiddlyTools.com/#RescueStoreAreaCommand|
|Version|1.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|script bookmarklet|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|rescue tiddler changes from online document when net goes down during editing|
%/<script label="$1" title="rescue tiddlers from current document storeArea">
if(typeof version==undefined||version.title!='TiddlyWiki')
{alert(document.location.href+'\n\nis not a TiddlyWiki document');return false;}
if (!confirm('Preparing to rescue storeArea contents... press OK to proceed')) return false;
var sa=store.allTiddlersAsHtml().htmlEncode();
var win=window.open();
win.document.open();
win.document['write']('<html><body><pre>'+sa+'</pre></body></html>');
win.document.close();
alert('copy/paste the displayed storeArea content into a local text file');
win.focus();
</script><script>
if ("$1"=="$"+"1") place.lastChild.innerHTML="Rescue current storeArea contents";
</script>
Here is an example expanding the rdist(1) configuration language to add a command to perform a diff between the master file and the file currently installed. It is called as:
{{{
ntp-verify:
$C/ntp/clients.conf -> ${NTP_SLAVES}
VERIFYFILE(/etc/ntp.conf);
}}}
{{{
#bigdef VERIFYFILE(TARGET)
install TARGET.verify ;
special "diff -u TARGET ${REMFILE}; exit=$?; rm -f ${REMFILE}; exit $exit"##
#endbigdef
}}}
{{{plod -G Programming}}}
{{overlay1{
{{{
-----
12/04/2009, 14:47 -- Programming:perl
working on a new release of plod
}}}
}}}
/***
|Name|SectionLinksPlugin|
|Source|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Documentation|http://www.TiddlyTools.com/#SectionLinksPlugin|
|Version|1.3.4|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|allow tiddler sections in TiddlyLinks to be used as anchor points|
This plugin enhances the processing of section references so they can be used in links to auto-scroll to the indicated heading within a tiddler (i.e., similar to the 'anchor' behavior provided in HTML by {{{<a name="foo">}}} and {{{<a href="#foo">...</a>}}})
!!!Usage
<<<
!!!!!{{{<<tiddler>>}}} macro
>The {{{<<tiddler SomeTiddler##SomeSection>>}}} syntax has been extended so that when the tiddler title is omitted or the 'here' keyword is used (e.g., {{{<<tiddler ##SomeSection>>}}} or {{{<<tiddler here##SomeSection>>}}}), then the current containing tiddler is implied by default.
!!!!!~TiddlyLink syntax
>the standard link syntax has been extended so that a section name can included in a tiddler link (e.g., {{{[[SomeTiddler##SomeSection]]}}}). When clicked, the tiddler is displayed and the specified section heading will be automatically scrolled into view. If the tiddler title is omitted or the 'here' keyword is used (e.g., {{{[[##SomeSection]]}}} or {{{[[here##SomeSection]]>>}}}), then the current containing tiddler is implied by default.
!!!!!"""<<sectionTOC>>""" macro
>This macro generates a 'Table of Contents'-style numbered-bullet list with links to all sections within the current tiddler. Simply place the following macro at the //end of the tiddler content// (i.e., following all section headings):
{{{
<<sectionTOC>> or <<sectionTOC className>>
}}}
>Note: The macro must occur at the end of the tiddler in order to locate the rendered section headings that precede it. In addition, to position the macro's //output// within the tiddler, you must create a special 'target element' that uses a specified classname (default='sectionTOC'), like this:
{{{
{{sectionTOC{}}}
}}}
>When the {{{<<sectionTOC>>}}} macro is rendered, it will find the matching 'sectionTOC'-classed element and writes it's output there. You can also add the macro and/or target elements directly to the [[ViewTemplate]] definition, so that every tiddler can automatically display the table of contents:
{{{
<span class='sectionTOC'></span> <!-- target element -->
...
<span macro='sectionTOC'></span> <!-- must be at end of tiddler -->
}}}
<<<
!!!Revisions
<<<
2009.08.21 [1.3.4] added handling to ignore leading/trailing whitespace in section references
2009.08.21 [1.3.3] in createTiddlyLink(), add tiddlyLinkNonExistingSection class if matching section is not found
2009.08.14 [1.3.2] in createTiddlyLink(), don't override core value for ~TiddlyLink attribute
2009.08.02 [1.3.1] in sectionTOC.handler(), trim leading/trailing whitespace from generated section links
2009.08.01 [1.3.0] in scrollToSection(), apply 3-tier section matching (exact, startsWith, contains)
2009.07.06 [1.2.2] fixed displayTiddler() hijack
2009.07.03 [1.2.1] in {{{<<sectionTOC>>}}}, suppress output if target is not found
2009.06.02 [1.2.0] added support for 'here' keyword in {{{[[here##section]]}}} links and {{{<<tiddler here##section>>}}} macro
2009.04.09 [1.1.1] in sectionTOC macro, make target visible when TOC is rendered.
2009.01.18 [1.1.0] added {{{<<sectionTOC>>}}} macro to generate numbered-bullet links to sections of current tiddler
2009.01.06 [1.0.0] converted to stand-alone plugin
2008.10.14 [0.0.0] initial release (as [[CoreTweaks]] #784 - http://trac.tiddlywiki.org/ticket/784)
<<<
!!!Code
***/
//{{{
version.extensions.SectionLinksPlugin= {major: 1, minor: 3, revision: 4, date: new Date(2009,8,21)};
Story.prototype.scrollToSection = function(title,section) {
if (!title||!section) return; var t=this.getTiddler(title); if (!t) return null;
var elems=t.getElementsByTagName('*'); var heads=[];
for (var i=0; i<elems.length; i++)
if (['H1','H2','H3','H4','H5'].contains(elems[i].nodeName)) heads.push(elems[i]);
for (var i=0; i<heads.length; i++)
if (getPlainText(heads[i]).trim()==section) break;
if (i==heads.length) for (var i=0; i<heads.length; i++)
if (getPlainText(heads[i]).trim().startsWith(section)) break;
if (i==heads.length) for (var i=0; i<heads.length; i++)
if (getPlainText(heads[i]).trim().indexOf(section)!=-1) break;
if (i<heads.length) { var h=heads[i];
// if section heading is collapsed, click to expand it - see [[FoldHeadingsPlugin]]
if (hasClass(h,'foldable') && h.nextSibling.style.display=='none') h.onclick();
// scroll *after* tiddler animation
var delay=config.options.chkAnimate?config.animDuration+100:0;
setTimeout('window.scrollTo('+findPosX(h)+','+findPosY(h)+')',delay);
return h;
}
}
//}}}
/***
!!!!core hijacks
***/
/***
!!!!!createTiddlyLink
***/
//{{{
// [[tiddlername##section]] and [[##section]]
if (!window.createTiddlyLink_section)
window.createTiddlyLink_section=window.createTiddlyLink;
window.createTiddlyLink=function(place,title) {
var t=story.findContainingTiddler(place); var tid=t?t.getAttribute('tiddler'):'';
var parts=title.split(config.textPrimitives.sectionSeparator);
var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
if (!title.length || title.toLowerCase()=='here') title=tid; // default=current tiddler
arguments[1]=title;
var btn=createTiddlyLink_section.apply(this,arguments);
if (section) {
btn.setAttribute('section',section);
if (store.getTiddlerText(title+config.textPrimitives.sectionSeparator+section)===null)
addClass(btn,'tiddlyLinkNonExistingSection');
}
return btn;
}
//}}}
/***
!!!!!onClickTiddlerLink
***/
//{{{
if (!window.onClickTiddlerLink_section)
window.onClickTiddlerLink_section=window.onClickTiddlerLink;
window.onClickTiddlerLink=function(ev) {
var e=ev||window.event; var target=resolveTarget(e); var title=null;
while (target!=null && title==null) {
title=target.getAttribute('tiddlyLink');
section=target.getAttribute('section');
target=target.parentNode;
}
var t=story.findContainingTiddler(target); var tid=t?t.getAttribute('tiddler'):'';
if (title!=tid||!section) // avoid excess scrolling for intra-tiddler links
onClickTiddlerLink_section.apply(this,arguments);
story.scrollToSection(title,section);
return false;
}
//}}}
/***
!!!!! displayTiddler
***/
//{{{
if (!Story.prototype.displayTiddler_section)
Story.prototype.displayTiddler_section=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler)
{
var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
var parts=title.split(config.textPrimitives.sectionSeparator);
var title=parts[0]; var section=parts[1]; if (section) section=section.trim();
if (!title.length || title.toLowerCase()=='here') {
var t=story.findContainingTiddler(place);
title=t?t.getAttribute('tiddler'):'';
}
arguments[1]=title; // default=current tiddler
this.displayTiddler_section.apply(this,arguments);
story.scrollToSection(title,section);
}
//}}}
/***
!!!!!isExternalLink
***/
//{{{
if (!config.formatterHelpers.isExternalLink_section)
config.formatterHelpers.isExternalLink_section=config.formatterHelpers.isExternalLink;
config.formatterHelpers.isExternalLink=function(link) {
if (link.indexOf(config.textPrimitives.sectionSeparator)!=-1) return false;
return config.formatterHelpers.isExternalLink_section.apply(this,arguments);
}
//}}}
/***
!!!!!tiddler.handler
***/
//{{{
if (!config.macros.tiddler.handler_section)
config.macros.tiddler.handler_section=config.macros.tiddler.handler;
config.macros.tiddler.handler=function(place,macroName,params,wikifier,paramString,tiddler)
{
if (!params[0]) return;
var sep=config.textPrimitives.sectionSeparator;
var parts=params[0].split(sep); var tid=parts[0]; var sec=parts[1]; if (sec) sec=sec.trim();
if ((tid.toLowerCase()=='here'||!tid.length) && sec) { // fixup for 'here##section' and '##section'
var here=story.findContainingTiddler(place)
var tid=here?here.getAttribute('tiddler'):tiddler?tiddler.title:'';
arguments[2][0]=tid+sep+sec;
arguments[4]=paramString.replace(new RegExp('(here)?'+sep+sec),tid+sep+sec);
}
config.macros.tiddler.handler_section.apply(this,arguments);
}
//}}}
/***
!!!!sectionTOC macro
***/
//{{{
config.macros.sectionTOC = {
targetClass: 'sectionTOC',
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var out=[];
var targetClass=params[0]||this.targetClass;
var t=story.findContainingTiddler(place); if (!t) return;
var elems=t.getElementsByTagName('*');
var level=5; // topmost heading level
for (var i=0; i<elems.length; i++) {
var txt=getPlainText(elems[i]).trim();
var link='[['+txt+'|##'+txt+']]';
switch(elems[i].nodeName) {
case 'H1': out.push('#'+link); level=1; break;
case 'H2': out.push('##'+link); level=level<2?level:2; break;
case 'H3': out.push('###'+link); level=level<3?level:3; break;
case 'H4': out.push('####'+link); level=level<4?level:4; break;
case 'H5': out.push('#####'+link); level=level<5?level:5; break;
default: if (hasClass(elems[i],targetClass)) var target=elems[i];
}
}
// trim excess bullet levels
if (level>1) for (var i=0; i<out.length; i++) out[i]=out[i].substr(level-1);
// show numbered list
if (out.length && target) {
if (target.style.display=='none') target.style.display='block';
wikify(out.join('\n'),target);
}
}
}
//}}}
/***
!!!Invoke macro
{{{
<<sectionTOC>>
}}}
***/
// //<<sectionTOC>>
/%
!info
|Name|ShowPopup|
|Source|http://www.TiddlyTools.com/#ShowPopup|
|Version|1.2.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transcluded html|
|Requires||
|Overrides||
|Description|display tiddler content in a TiddlyWiki popup panel|
Usage:
<<<
{{{
<<tiddler ShowPopup with: TiddlerName label tooltip buttonClass width popupClass>>
}}}
where:
*''~TiddlerName''<br>title of the tiddler to be displayed
*''label''<br>text for the command link
*''tooltip''<br>mouseover help text for the link
*''buttonClass''<br>CSS classname applied to the command text (default=button)
*''width''<br>width of the popup (using CSS measurements, default=auto)
*''popupClass''<br>CSS classname applied to the popup panel (default=none).<br>Use 'sticky' for persistent popups (see StickyPopupPlugin)
<<<
Example:
<<<
{{{
<<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
}}}
<<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
<<<
!end
!show
<html><hide linebreaks>
<a href="javascript:;" class="$4" title="$3" onclick="
var p=Popup.create(this); if(!p)return;
p.className+='$6'!='$'+'6'?' $6':'';
var d=createTiddlyElement(p,'div');
var s=d.style;
s.whiteSpace='normal';
s.width='$5'!='$'+'5'?'$5':'auto';
s.padding='2px';
wikify(store.getTiddlerText('$1',''),d);
Popup.show();
event.cancelBubble=true;
if(event.stopPropagation)event.stopPropagation();
return(false);
">$2</a></html>
!end
%/<<tiddler {{'ShowPopup##'+('$1'=='$'+'1'?'info':'show')}} with: [[$1]] [[$2]] [[$3]] [[$4]] [[$5]] [[$6]]>>
A sample of a password file generation tool. Using
{{{
filepp -D SERVICES="BIND POSTFIX" password.template
}}}
the named and postfix users will be generated.
{{{
#if "SERVICES" =~ /\bBIND\b/
named:x:25:25:Named:/var/named:/sbin/nologin
#endif
#if "SERVICES" =~ /POSTGRES/
postgres:x:26:26:PostgreSQL Server:...
#endif
#if "SERVICES" =~ /POSTFIX/
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
#endif
}}}
/% This tiddler is included by the PageTemplate and is used to trigger macro invocations. It should not actually
display anything. All the macros here are invoked for their side effects and not for display. %/
/% A seperate tiddler for items to be executed only in the instructors cousebook. Since this tiddler is missing
from the student coursebook copy it will have not effect for the student %/
<<tiddler InstructorSiteStartup>>
/% all references to tiddlywiki should point to TiddlyWiki %/
<<redirectExact tiddlywiki TiddlyWiki>>
John Rouillard - BBlisa Dec 9 2009
http://www.example.com/class/content.html
<<tiddler Welcome/coursebook>>
/***
|''Name:''|SlideShowPlugin|
|''Description:''|Creates a slide show from a group of tiddlers|
|''Author:''|Paulo Soares|
|''Contributors:''|John P. Rouillard|
|''Version:''|2.1.2|
|''Date:''|2009-11-29|
|''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|
|''Documentation:''|[[SlideShowPlugin Documentation|SlideShowPluginDoc]]|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.5.0|
***/
//{{{
if(!version.extensions.SlideShowPlugin) { //# ensure that the plugin is only installed once
version.extensions.SlideShowPlugin = {installed: true};
(function($) {
config.macros.slideShow = {maxTOCLength: 30};
config.macros.slideShow.text = {
label: "slide show", tooltip: "Start slide show",
quit: {label: "x", tooltip: "Quit the slide show"},
firstSlide: {label: "<<", tooltip: "Go to first slide"},
previous: {label: "<", tooltip: "Go back"},
next: {label: ">", tooltip: "Advance"},
lastSlide: {label: ">>", tooltip: "Go to last slide"},
goto: {label: "Go to slide:"},
resetClock: {tooltip: "Reset the clock"},
overlay: "overlay"
};
config.macros.slideShow.handler = function(place,macroName,params,wikifier,paramString){
var args = paramString.parseParams(null,null,false);
this.label = getParam(args,"label",this.text.label);
this.tooltip = getParam(args,"tooltip",this.text.tooltip);
var onclick = function(){config.macros.slideShow.onClick(place,paramString); return false;};
createTiddlyButton(place,this.label,this.tooltip,onclick);
return false;
}
config.macros.slideShow.onClick = function(place,paramString) {
var slide, cm = config.macros.slideShow;
var title = story.findContainingTiddler(place);
title = title ? title.getAttribute("tiddler") : null;
var args = paramString.parseParams(null,null,false);
title = getParam(args,"tiddler",title);
var argsArray = paramString.readMacroParams();
this.clicks = ($.inArray('noClicks',argsArray) < 0);
this.keyboard = ($.inArray('noKeyboard',argsArray) < 0);
this.showAll = ($.inArray('showAll',argsArray) > -1);
this.cycle = ($.inArray('cycle',argsArray) > -1);
this.overlays = ($.inArray('noOverlays',argsArray) < 0);
this.theme = getParam(args,"theme");
this.tag = getParam(args,"tag");
this.toc = getParam(args,"toc","headers");
this.sort = getParam(args,"sort");
this.clockFormat = getParam(args,"clockFormat",'0hh:0mm:0ss');
this.auto = getParam(args,"auto",0);
this.header = getParam(args,"header",title);
this.footer = getParam(args,"footer","");
this.clock = getParam(args,"clock");
this.blocked = 0;
if(this.clock){
var startTime = new Date(0);
this.clockCorrection=startTime.getTimezoneOffset()*60000;
startTime = new Date();
this.clockMultiplier = 1;
this.clockInterval = 0;
var clockType= parseFloat(this.clock);
if(clockType < 0) {
this.clockMultiplier = -1;
this.clockInterval = -clockType*60000;
} else if(clockType == 0){
this.clockCorrection = 0;
startTime = new Date(0);
}
this.clockStartTime=startTime.getTime();
}
this.slides = [];
this.openTiddlers = [];
$("#tiddlerDisplay > *").each(function(){cm.openTiddlers.push($(this).attr('tiddler'))});
var count = 0;
this.slideTOC=[];
if(this.tag){
var content = store.getTaggedTiddlers(this.tag,this.sort);
$.each(content, function(){
count++;
cm.buildTOC(count,this.title);
cm.slides.push(this.title);
});
} else {
story.displayTiddler(null,title);
var list = $('[tiddler='+title+']'+" .tiddlyLinkExisting");
$.each(list,function(){
if(!$(this).parents().hasClass("exclude")){
slide = $(this).attr('tiddlylink');
count++;
cm.buildTOC(count,slide);
cm.slides.push(slide);
}
});
}
this.nSlides = this.slides.length;
if(this.nSlides==0) return false;
clearMessage();
this.toggleSlideStyles();
if(!this.showAll){
//Attach the key and mouse listeners
if(this.keyboard && !$("#tiddlerDisplay").hasClass("noKeyboard")) $(document).keyup(cm.keys);
if(this.clicks){
$("#displayArea").mouseup(cm.clicker);
document.oncontextmenu = function(){return false;}
}
if(this.clock) this.slideClock=setInterval(this.setClock, 1000);
if(this.auto>0){
this.autoAdvance=setInterval(cm.next, this.auto*1000);
}
this.showSlide(1);
} else {
story.closeAllTiddlers();
story.displayTiddlers(null,this.slides);
$(".tiddler").attr("ondblclick",null);
$(document).keyup(cm.endSlideShow);
}
return false;
}
config.macros.slideShow.buildNavigator = function() {
//Create the navigation bar
var i, slidefooter = $("#controlBar")[0];
if(!slidefooter) return;
$(slidefooter).addClass("slideFooterOff noClicks");
var navigator = createTiddlyElement(slidefooter,"SPAN","navigator");
var buttonBar = createTiddlyElement(navigator,"SPAN","buttonBar");
//Make it so that when the footer is hovered over the class will change to make it visible
$(slidefooter).bind("mouseenter mouseleave", function(e){$(this).toggleClass("slideFooterOff");});
//Create the control buttons for the navigation
createTiddlyButton(buttonBar,this.text.firstSlide.label,this.text.firstSlide.tooltip,this.firstSlide,"button");
createTiddlyButton(buttonBar,this.text.previous.label,this.text.previous.tooltip,this.previous,"button");
createTiddlyButton(buttonBar,this.text.quit.label,this.text.quit.tooltip,this.endSlideShow,"button");
createTiddlyButton(buttonBar,this.text.next.label,this.text.next.tooltip,this.next,"button");
createTiddlyButton(buttonBar,this.text.lastSlide.label,this.text.lastSlide.tooltip,this.lastSlide,"button");
if(this.clock){
if(this.clock == 0){
createTiddlyElement(navigator,"SPAN","slideClock");
} else {
createTiddlyButton(navigator," ",this.text.resetClock.tooltip,this.resetClock,"button","slideClock");
}
this.setClock();
}
var index = createTiddlyElement(slidefooter,"SPAN","slideCounter");
index.onclick = this.toggleTOC;
var toc = createTiddlyElement(slidefooter,"SPAN","toc");
var tocLine;
for(i=0; i<this.slideTOC.length; i++){
$(toc).append(this.slideTOC[i][2]);
tocLine = toc.lastChild;
$(tocLine).addClass("tocLevel"+this.slideTOC[i][1]).css("cursor", "pointer").hover(function () {
$(this).addClass("highlight");}, function () {
$(this).removeClass("highlight");});
tocLine.setAttribute("slide",this.slideTOC[i][0]);
$(tocLine).click(config.macros.slideShow.showSlideFromTOC);
}
//Input box to jump to specific slide
var tocItem = createTiddlyElement(toc,"DIV","jumpItem",null,this.text.goto.label);
var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");
tocJumpInput.type="text";
$(tocJumpInput).keyup(config.macros.slideShow.jumpToSlide);
}
//Used to shorten the TOC fields
config.macros.slideShow.abbreviate = function(label){
if(label.length>this.maxTOCLength) {
var temp = new Array();
temp = label.split(' ');
label = temp[0];
for(var j=1; j<temp.length; j++){
if((label.length+temp[j].length)<=this.maxTOCLength){
label += " " + temp[j];
} else {
label += " ...";
break;
}
}
}
return label;
}
config.macros.slideShow.buildTOC = function(count,title) {
var level = 1, text;
switch(this.toc){
case "headers":
var frag = wikifyStatic(store.getTiddlerText(title));
text = frag.replace(/<div class="comment">.*<\/div>/mg,"");
var matches = text.match(/<h[123456]>.*?<\/h[123456]>/mgi);
if(matches){
for (var j=0; j<matches.length; j++){
level = matches[j].charAt(2);
text = matches[j].replace(/<\/?h[123456]>/gi,"");
text = this.abbreviate(text);
this.slideTOC.push([count,level,"<div>("+count+") "+text+"</div>"]);
}
}
break;
case "titles":
text = this.abbreviate(title);
this.slideTOC.push([count,level,"<div>("+count+") "+text+"</div>"]);
}
}
config.macros.slideShow.showSlideFromTOC = function(e) {
var cm = config.macros.slideShow;
var slide = parseInt(e.target.getAttribute('slide'));
$("#toc").hide();
cm.showSlide(slide);
return false;
}
config.macros.slideShow.toggleTOC = function(){
$("#toc").toggle();
$("#jumpInput").focus().val('');
return false;
}
config.macros.slideShow.isInteger = function(s){
for (var i = 0; i < s.length; i++){
// Check that current character is number
var c = s.charAt(i);
if (((c < "0") || (c > "9"))) return false;
}
// All characters are numbers
return true;
}
config.macros.slideShow.jumpToSlide = function(e){
var cm = config.macros.slideShow;
if(e.which==13){
var input= $("#jumpInput").val();
if(cm.isInteger(input) && input>0 && input<=cm.nSlides){
$("#toc").hide();
cm.showSlide(input);
} else {$("#jumpInput").val('');}
}
return false;
}
config.macros.slideShow.toggleSlideStyles = function(){
var contentWrapper = $('#contentWrapper');
if(contentWrapper.hasClass("slideShowMode")){
refreshPageTemplate();
removeStyleSheet("SlideShowStyleSheet");
if(this.theme) removeStyleSheet(this.theme);
} else {
$("#displayArea").prepend('<div id="slideBlanker" style="display:none"></div><div id="slideHeader">'+this.header+'</div><div id="slideFooter">'+this.footer+'</div><div id="controlBar"></div>');
setStylesheet(store.getRecursiveTiddlerText("SlideShowStyleSheet"),"SlideShowStyleSheet");
if(this.theme && store.tiddlerExists(this.theme)){setStylesheet(store.getRecursiveTiddlerText(this.theme),this.theme);}
this.buildNavigator();
}
contentWrapper.toggleClass("slideShowMode");
return false;
}
config.macros.slideShow.showSlide = function(n){
if(this.cycle) {
if(n>this.nSlides) {
n = 1;
} else if(n<1) {
n = this.nSlides;
}
} else {
if(n>this.nSlides || n<1) return;
}
story.closeAllTiddlers();
if(this.clock=='-'){this.resetClock();}
story.displayTiddler(null,String(this.slides[n-1]));
$(".tiddler").attr("ondblclick",null);
this.curSlide = n;
$("#slideCounter").text(this.curSlide+"/"+this.nSlides);
if(this.overlays){
var contents = $(".viewer *");
this.numOverlays = 1;
while(1){
if(contents.hasClass(this.text.overlay+this.numOverlays)){
this.numOverlays++;
} else {break;}
}
this.numOverlays--;
this.showOverlay(0);
}
return false;
}
config.macros.slideShow.showOverlay = function(n){
var i, set, cm = config.macros.slideShow;
if(!cm.overlays || cm.numOverlays == 0 || n<0 || n>cm.numOverlays){return;}
for(i=1; i<n; i++){
set = $(".viewer "+"."+cm.text.overlay+i);
set.removeClass("currentOverlay nextOverlay");
set.addClass("previousOverlay");
}
set = $(".viewer "+"."+cm.text.overlay+n);
set.removeClass("previousOverlay nextOverlay");
set.addClass("currentOverlay");
for(i=n; i<config.macros.slideShow.numOverlays; i++){
set = $(".viewer "+"."+cm.text.overlay+(i+1));
set.removeClass("previousOverlay currentOverlay");
set.addClass("nextOverlay");
}
cm.curOverlay = n;
}
config.macros.slideShow.firstSlide = function(){
config.macros.slideShow.showSlide(1);
return false;
}
config.macros.slideShow.lastSlide = function(){
config.macros.slideShow.showSlide(config.macros.slideShow.nSlides);
return false;
}
config.macros.slideShow.next = function(){
var cm = config.macros.slideShow;
if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == cm.numOverlays) {
cm.showSlide(cm.curSlide+1);
} else {
cm.showOverlay(cm.curOverlay+1);
}
return false;
}
config.macros.slideShow.previous = function(){
var cm = config.macros.slideShow;
if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == 0) {
cm.showSlide(cm.curSlide-1);
cm.showOverlay(cm.numOverlays);
} else {
cm.showOverlay(cm.curOverlay-1);
}
return false;
}
config.macros.slideShow.endSlideShow=function(){
var cm = config.macros.slideShow;
if(cm.autoAdvance) {clearInterval(cm.autoAdvance);}
if(this.clock) clearInterval(this.slideClock);
story.closeAllTiddlers();
cm.toggleSlideStyles();
story.displayTiddlers(null,cm.openTiddlers);
$(document).unbind();
document.oncontextmenu = function(){};
return false;
}
// 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)
config.macros.slideShow.keys = function(key) {
var cm = config.macros.slideShow;
switch(key.which) {
case 32: // spacebar
if(cm.auto>0 && cm.blocked==0){
if(cm.autoAdvance){
clearInterval(cm.autoAdvance);
cm.autoAdvance = null;
} else {
cm.autoAdvance=setInterval(cm.next, cm.auto*1000);
}
} else {
if(cm.blocked==0) cm.next();
}
break;
case 34: // page down
if(cm.blocked==0) cm.showSlide(cm.curSlide+1);
break;
case 39: // rightkey
if(cm.blocked==0) cm.next();
break;
case 40: // downkey
if(cm.blocked==0) cm.showOverlay(cm.numOverlays);
break;
case 33: // page up
if(cm.blocked==0) cm.showSlide(cm.curSlide-1);
break;
case 37: // leftkey
if(cm.blocked==0) cm.previous();
break;
case 38: // upkey
if(cm.blocked==0) cm.showOverlay(0);
break;
case 36: // home
if(cm.blocked==0) cm.firstSlide();
break;
case 35: // end
if(cm.blocked==0) cm.lastSlide();
break;
case 27: // escape
cm.endSlideShow();
break;
case 66: // B
$("#slideBlanker").toggle();
cm.blocked = (cm.blocked +1)%2;
break;
}
return false;
}
config.macros.slideShow.clicker = function(e) {
var cm = config.macros.slideShow;
if(cm.blocked==1 || $(e.target).attr('href') || $(e.target).parents().andSelf().hasClass('noClicks')){
return true;
}
if($("#toc").is(':visible')){
cm.toggleTOC();
} else {
if((!e.which && e.button == 1) || e.which == 1) {
cm.next();
}
if((!e.which && e.button == 2) || e.which == 3) {
cm.previous();
}
}
return false;
}
config.macros.slideShow.setClock = function(){
var cm = config.macros.slideShow;
var actualTime = new Date();
var newTime = actualTime.getTime() - cm.clockStartTime;
newTime = cm.clockMultiplier*newTime+cm.clockInterval+cm.clockCorrection;
actualTime.setTime(newTime);
newTime = actualTime.formatString(cm.clockFormat);
$("#slideClock").text(newTime);
return false;
}
config.macros.slideShow.resetClock = function(){
var cm = config.macros.slideShow;
if(cm.clock == 0) return;
var time = new Date(0);
if(cm.clockStartTime>time){
var startTime = new Date();
cm.clockStartTime=startTime.getTime();
}
return false;
}
config.shadowTiddlers.SlideShowStyleSheet="/*{{{*/\n.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{\n display:none !important\n}\n\n#slideBlanker{\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 90; \n background-color: #000;\n opacity: 0.9;\n filter: alpha(opacity=90)\n}\n\n.nextOverlay{\n visibility: hidden\n}\n\n.previousOverlay,.currentOverlay{\n visibility: visible\n}\n\n#displayArea{\n font-size: 250%;\n margin: 0 !important;\n padding: 0\n}\n\n#controlBar{\n position: fixed;\n bottom: 2px;\n right: 2px;\n width: 100%;\n text-align: right\n}\n\n#controlBar .button{\n margin: 0 0.25em;\n padding: 0 0.25em\n}\n\n#slideHeader{\n font-size: 200%;\n font-weight: bold\n}\n\n#slideFooter{\n position: fixed;\n bottom: 2px\n}\n\n.slideFooterOff #navigator{\n visibility: hidden\n}\n\n#slideClock{\n margin: 0 5px 0 5px\n}\n\n#slideCounter{\n cursor: pointer;\n color: #aaa\n}\n\n#toc{\n display: none;\n position: absolute;\n font-size: .75em;\n bottom: 2em;\n right: 0;\n background: #fff;\n border: 1px solid #000;\n text-align: left\n}\n\n#jumpItem{\n padding-left:0.25em\n}\n\n#jumpInput{\n margin-left: 0.25em;\n width: 3em\n}\n\n.tocLevel1{\n font-size: .8em\n}\n\n.tocLevel2{\n margin-left: 1em;\n font-size: .75em\n}\n\n.tocLevel3{\n margin-left: 2em;\n font-size: .7em\n}\n\n.tocLevel4{\n margin-left: 3em;\n font-size: .65em\n}\n\n.tocLevel5{\n margin-left: 4em;\n font-size: .6em\n}\n\n.tocLevel6{\n margin-left: 5em;\n font-size: .55em\n}\n/*}}}*/";
config.shadowTiddlers.SlideShowPluginDoc="The documentation is available [[here|http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPluginDoc]].";
})(jQuery)
}
//}}}
!Description
This plugin turns a set of tiddlers into a slide show. A single macro provides a flexible way to present a set of tiddlers, including:
#a full screen presentation that hides the TiddlyWiki structure (header, sidebar, main menu);
#a way to navigate through a set of tiddlers keeping the TiddlyWiki structure (similar to the [[NavigationMacro|http://tw.lewcid.org/#NavigationMacro]] by Saq Imtiaz);
#a display of all the selected tiddlers ready to be printed.
!Main features
Most features that are usually found in presentation software are available.
*Build a slide show from a list of tiddlers' titles or selecting a specific tag with optional sort
*Fully customizable presentations (CSS knowledge required)
*Auto-advancing slide show (kiosk mode) and looping (circular mode)
*Incremental display (several overlays or layers in a slide)
*Optional clock with 4 different modes:
**local time
**elapsed time of presentation
**elapsed time for each slide
**countdown clock for a given period
*Screen blanking for pauses
!Installation
To install this plugin copy the tiddler SlideShowPlugin to your TiddlyWiki, label it with the ''systemConfig'' tag, save the TW and refresh the browser.
Optionally, you can also copy this documentation tiddler. If you don't, a link to the original one in my site is provided.
!Quick start
The simplest way to make a slide show is to create a new tiddler with references to all the tiddlers you want to include in your presentation. Any reference or group of references to tiddlers that should be skipped must be wrapped in a {{{exclude}}} class as in the following example:
{{{
MissingSlide
[[First slide|SlideShowExample-1]] {{exclude{(the tiddler SlideShowPluginDoc will not be included in the presentation)}}}
SlideShowExample-2
SlideShowExample-3
SlideShowExample-4
}}}
Add {{{<<slideShow>>}}} anywhere in the tiddler, close the edit form, click the ''slide show'' button and there you are. Move forward/backward in the presentation with the mouse left/right button. If you move the mouse pointer over the bottom of the browser window you will see a few navigation buttons. Click the ''x'' button or press the ''Escape'' key to exit.
!Options
{{{
<<slideShow
noClicks
noKeyboard
noOverlays
cycle
showAll
tiddler:tiddler
label:string
tooltip:string
tag:tag
sort:field
theme:tiddler
toc:string
auto:time
clock:type
clockFormat:string
header:string
footer:string
>>
}}}
''noClicks''
Disables navigation through mouse clicks on the tiddlers. This is useful when there are lots of clickable elements in the presentation.
If you want to keep using the mouse to move around the presentation and there are occasional elements that require mouse clicking, these can be formatted with a {{{noClicks}}} class (read more [[here|http://www.tiddlywiki.com/#CustomCssClass]]).
''noKeyboard''
Disables keyboard navigation.
''noOverlays''
Disables the incremental display of overlays.
''cycle''
The slide shows runs in a continuous loop.
''showAll''
To print a presentation all the selected tiddlers are opened in the specified order. Press any key to return to the default TiddlyWiki layout.
''tiddler''
Use this option to indicate the tiddler where your slide show is defined when it is not the same one that contains the button that starts the presentation.
''label''
Text to replace the default text in the slide show button.
''tooltip''
Text to be shown when the mouse is over the slide show button.
''tag''
Use this option to create a slide show with the tiddlers with the provided tag instead of providing a list of tiddlers.
''sort''
If the ''tag'' option is used you can use this other option to sort the tiddlers according to a specific field. Valid values are: //created// (default), //modified//, //title// and //text//.
''theme''
A user provided tiddler containing CSS rules that define the style of the slide show. To redefine the default style, edit the SlideShowStyleSheet shadow tiddler.
''toc''
Choose the type of table of contents. Possible values: ''titles'' will enable the use of the tiddlers titles, ''headers'' (default) to choose html headers (h1, h2,...), anything else will disable the table of contents.
''auto''
The slide show auto advances after the defined number of seconds. The slide show can be paused by pressing the ''space bar''.
''clock''
Displays a clock near the navigation buttons at the bottom of the screen. Four types of clocks can be defined:
#''clock:0'' -- shows the local time.
#''clock:'+''' -- displays the elapsed time of the presentation. Click the clock display to reset the time.
#''clock:'-''' -- displays the elapsed for each slide. Click the clock display to reset the time.
#''clock:-20'' -- displays a countdown clock for the given (negative) number of minutes. Click the clock display to reset the time.
''clockFormat''
A string that defines the clock format. The default is '0hh:0mm:0ss' where the prefix '0' forces a leading zero.
''header''
A string to be used as a permanent header for the slide show. By default it's used the title of tiddler that defines the slide show.
''footer''
A string to be used as a permanent footer for the slide show. By default the footer is empty.
!Incremental display
A succession of overlays (or layers) can be defined in each slide by marking blocks of text with
{{{
{{overlay1{...some text...}}}, {{overlay2{...some text...}}}, {{overlay3{...some text...}}}, ...
}}}
The default name of the classes (//overlay//) can be redefined with //config.macros.slideShow.text.overlay = "layer"//, for example.
To costumize the way overlays are shown you can redefine the following CSS classes
*.previousOverlay
*.currentOverlay
*.nextOverlay
in a ~StyleSheet. The default style simply hides the next overlays and shows the current and the previous ones as normal text.
!Slide show navigation
You can navigate through a slide show using the keyboard or the mouse.
!!Mouse navigation
Left (right) clicking on a slide jumps to the next (previous) slide or overlay. To move to the first or last slides you must use the navigation bar at the bottom of the browser's window.
!!Keyboard
The following keys are defined:
*Home - first slide
*~PageUp - previous slide
*~PageDown - next slide
*End - last slide
*Escape - exit slide show
*Up arrow - first overlay
*Left arrow - previous overlay/slide
*Pause/Right arrow - next overlay/slide
*Down arrow - last overlay
*Spacebar - pause/resume slide show in auto advance mode, next overlay/slide otherwise
*B - blank screen and block the slide show
!Miscellaneous
Any block of text marked as
{{{
{{comment{For my eyes only!}}}
}}}
will not be displayed in the slide show.
All translatable strings are defined in //config.macros.slideShow.text// parameter. See SlideShowPluginMsgPT with the portuguese translation as an example.
/*{{{*/
/* Default slide show style sheet settings */
.header, #mainMenu, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
display:none !important
}
#slideBlanker{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 90;
background-color: #000;
opacity: 0.9;
filter: alpha(opacity=90)
}
.nextOverlay{
visibility: hidden
}
.previousOverlay,.currentOverlay{
visibility: visible
}
#displayArea{
font-size: 250%;
margin: 0 !important;
padding: 0
}
#controlBar{
position: fixed;
bottom: 2px;
right: 2px;
width: 100%;
text-align: right
}
#controlBar .button{
margin: 0 0.25em;
padding: 0 0.25em
}
#slideHeader{
font-size: 200%;
font-weight: bold
}
#slideFooter{
position: fixed;
bottom: 2px
}
.slideFooterOff #navigator{
visibility: hidden
}
#slideClock{
margin: 0 5px 0 5px
}
#slideCounter{
cursor: pointer;
color: #aaa
}
#toc{
display: none;
position: absolute;
font-size: .75em;
bottom: 2em;
right: 0;
background: #fff;
border: 1px solid #000;
text-align: left
}
#jumpItem{
padding-left:0.25em
}
#jumpInput{
margin-left: 0.25em;
width: 3em
}
.tocLevel1{
font-size: .8em
}
.tocLevel2{
margin-left: 1em;
font-size: .75em
}
.tocLevel3{
margin-left: 2em;
font-size: .7em
}
.tocLevel4{
margin-left: 3em;
font-size: .65em
}
.tocLevel5{
margin-left: 4em;
font-size: .6em
}
.tocLevel6{
margin-left: 5em;
font-size: .55em
}
/* local changes for coursebook */
/* Disable slide blanker */
#slideBlanker {
opacity: 0.0;
filter: alpha(opacity=0)
}
/* Don't do overlay displays, display whole thing at once. */
.nextOverlay{
visibility: visible
}
/* navigator always visible, black text on white background */
.slideFooterOff #navigator{
visibility: visible;
background: #FFF;
foreground: #000;
}
#displayArea{
font-size: 130%;
}
.title {
display: block !important;
left-margin: 6em;
}
/* put control bar in top right of header */
#controlBar{
position: relative;
bottom: 2px;
right: 2px;
width: 100%;
text-align: right;
}
#controlBar .button {
border: 2px solid #000;
border-style: outset;
}
/* put toc as drop down menu not drop up */
#toc{
font-size: 1em;
top: 2em;
right: 0;
background: #888;
}
/* display comments in student mode with sea green background */
#contentWrapper.slideShowMode .comment{
display: block !important;
background: #FFCC00;
}
.notes {
display: block;
}
#openTiddlers { display: none !important }
/*}}}*/
!PageTemplate
<!--{{{-->
<div id='displayArea'>
<div id='slideBlanker' style='display:none'></div>
<div id='slideHeader'></div>
<div id='tiddlerDisplay'></div>
<div id='slideFooter'></div>
<div id='controlBar' class='slideFooterOff noClicks'></div>
</div>
<!--}}}-->
!ViewTemplate
<!--{{{-->
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<!--}}}-->
!contentViewTemplate
<!--{{{-->
theme
<div class='title' macro='view title'></div>
<div class='viewer' macro='view text wikified'></div>
<!--}}}-->
!StyleSheet
/*{{{*/
#slideBlanker{
position:absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 90;
background-color: #000;
opacity:.9;filter: alpha(opacity=90);
}
#backstageShow, #contentWrapper.slideShowMode .comment{
display: none !important;
}
#contentWrapper.slideShowMode .nextOverlay{
visibility: hidden;
}
#contentWrapper.slideShowMode .previousOverlay, #contentWrapper.slideShowMode .currentOverlay{
visibility: visible;
}
#contentWrapper.slideShowMode #displayArea{
font-size: 220%;
margin: 0 !important;
padding: 0;
}
#controlBar{
position: fixed;
bottom: 2px;
right: 2px;
width: 100%;
text-align: right;
}
#controlBar .button{
margin:0em 0.25em;
padding:0em 0.25em;
}
#slideHeader{
font-size: 200%;
font-weight: bold;
}
#slideFooter{
position: absolute;
bottom: 2px;
font-size: 50%;
}
.slideFooterOff #navigator{
visibility: hidden;
}
#slideClock{
margin: 0 5px 0 5px
}
#slideCounter{
cursor: pointer;
}
#toc{
display: none;
position: absolute;
font-size: .75em;
bottom: 2em;
right: 0;
background: #fff;
border: 1px solid #000;
text-align: left;
}
.tocJumpItem input{
margin-left: 1em;
width: 3em
}
.tocLevel1{
font-size: .8em;
}
.tocLevel2{
margin-left: 1em;
font-size: .75em;
}
.tocLevel3{
margin-left: 2em;
font-size: .7em;
}
.tocLevel4{
margin-left: 3em;
font-size: .65em;
}
.tocLevel5{
margin-left: 4em;
font-size: .6em;
}
.tocLevel6{
margin-left: 5em;
font-size: .55em;
}
/*}}}*/
These sections are used in presentations to provide the text before the buttons that start the slideshows (so the tiddlers mentioned aren't included in the slideshow). Make sure each section is only one line. No blank lines as they display as blank lines when used. The end section merely defines the end for the print section.
!Instructor
Instructor show with theme {{exclude{[[InstructorSlideShowStyleSheet]]}}}:
!Student
Student show using {{exclude{[[SlideShowStyleSheet]]}}}:
!Print
Print show with theme {{exclude{[[PrintingSlideShowStyleSheet]]}}}:
!end