Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
<<tiddler {{
var here=story.findContainingTiddler(place);
var target=document.getElementById('$2')||here||place.parentNode;
if (target==here) { // in a tiddler, get viewer element
var elems=target.getElementsByTagName('*');
for (var i=0;i<elems.length;i++)
if (hasClass(elems[i],'viewer')) { target=elems[i]; break; }
}
if (target) {
var mode='$1'; if (mode=='$'+'1') mode='on';
if (['on','enable','force'].contains(mode.toLowerCase())) {
var title=target.getAttribute('tiddler');
if (!title&&here) title=here.getAttribute('tiddler');
if (title) target.setAttribute('tiddler',title);
target.setAttribute('refresh','content');
target.setAttribute('force',(mode=='force')?'true':'');
} else if (['off','disable'].contains(mode.toLowerCase())) {
target.setAttribute('refresh','');
target.setAttribute('force','');
}
}
'';}}>>
/***
|Name|CleanTiddlerPlugin|
|Description|Plugin to clean up and partially wikify Word HTML|
|Author|Jonathan Overett Somnier|
|Contributors|Based on [[Word HTML Cleaner|http://ethilien.net/websoft/wordcleaner/cleaner.htm]] (C) 2005 Connor McKay|
|Source|http://jos.tiddlyspot.com/#CleanTiddlerPlugin|
|Version|0.2|
|~CoreVersion|2.2|
|Licence|GNU General Public License version 2|
!!!!!Documentation
After copying and pasting content from Microsoft Word into a tiddler being edited using [[EasyEditPlugin|http://visualtw.ouvaton.org/VisualTW.html#EasyEditPlugin]], a lot of Word metadata remains in the content which slows display and can significantly increase the size of the tiddler and so your Tiddlywiki which ultimately will affect performance.
CleanTiddlerPlugin provides a 'clean' toolbar command which will remove most of this metadata. It will also remove most formatting to enable tiddlers to be presented with a consistent appearance. So, changes in font, size and colour are removed while bold and italic styling is retained.
The plugin also tries to identify lists, headings and links and convert these into Tiddlywiki markup. This reflects the particular setup of the wikis created by the author which use the [[HTMLFormattingPlugin|http://www.TiddlyTools.com/#HTMLFormattingPlugin]] together with [[SectionLinksPlugin|http://www.TiddlyTools.com/#SectionLinksPlugin]] to provide automatic tables of contents based on headings in the tiddler.
!!!!!Code
***/
//{{{
config.commands.cleanTiddler = {
text: "clean",
tooltip: "Clean up the formatting of the article"
};
config.commands.cleanTiddler.handler = function(event,src,title) {
var tiddler = store.getTiddler(title);
if (tiddler) {
var text = tiddler.text;
if (text) {
if (TLChangesAllowed())
{
TiddlyLock.OldLockData = TiddlyLock.LockData;
TLLock();
text = cleanHTML(text);
TLUnlock(new Date().TLConvertToYYYYMMDDHHMMSSMMM());
store.saveTiddler(title,title,text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
if (config.options.chkAutoSave) saveChanges();
}
} else {
displayMessage("No article available for cleaning");
}
}
return false;
};
function cleanHTML(text)
{
//remplacement characters
var rchars = [["ñ","ó", "ë", "í", "ì", "î", '†'], ["-", "-", "'", "'", '"', '"', ' ']];
//allowed tags
var tags = ['html', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'ul', 'ol', 'li', 'u', 'i', 'b', 'a', 'table', 'tr', 'th', 'td', 'img', 'em', 'strong', 'br'];
//tags which should be removed when empty
var rempty = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'ul', 'ol', 'li', 'u', 'i', 'b', 'a', 'table', 'tr', 'em', 'strong'];
//allowed atributes for tags
var aattr = new Array();
aattr['a'] = ['href'];
aattr['table'] = ['border'];
aattr['th'] = ['colspan', 'rowspan'];
aattr['td'] = ['colspan', 'rowspan'];
aattr['img'] = ['src', 'width', 'height', 'alt'];
//tags who's content should be deleted
var dctags = ['head'];
//Quote characters
var quotes = ["'", '"'];
//tags which are displayed as a block
var btags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'br'];
//d = data, o = out, c = character, n = next character
//in and out variables
var d = text;
var o = '';
//Replace all whitespace characters with spaces
// d = d.replace(/(\s| )+/g, ' ');
d = d.replace(/\n+/g,"\n");
//replace weird word characters
for (i = 0; i < rchars[0].length; i++)
d = d.replace(new RegExp(rchars[0][i], 'g'), rchars[1][i]);
//initialize flags
//what the next character is expected to be
var expected = '';
//tag text
var tag = '';
//tag name
var tagname = '';
//what type of tag it is, start, end, or single
var tagtype = 'start';
//attribute text
var attribute = '';
//attribute name
var attributen = '';
//if the attribute has had an equals sign
var attributeequals = false;
//if attribute has quotes, and what they are
var attributequotes = '';
var c = '';
var n = '';
/*Parser format:
The parser is divided into three parts:
The first section is for when the current type of character is known
The second is for when it is an unknown character in a tag
The third is for anything outside of a tag
*/
//editing pass
for (i = 0; i < d.length; i++)
{
//current character
c = getc(d,i);
//next character
n = getc(d,i+1);
//***Section for when the current character is known
//if the tagname is expected
if (expected == 'tagname')
{
tagname += c.toLowerCase();
//lookahead for end of tag name
if (n == ' ' || n == '>' || n == '/')
{
tag += tagname;
expected = 'tag';
}
}
//if an attribute name is expected
else if (expected == 'attributen')
{
attributen += c.toLowerCase();
//lookahead for end of attribute name
if (n == ' ' || n == '>' || n == '/' || n == '=')
{
attribute += attributen;
//check to see if its an attribute without an assigned value
//determines whether there is anything but spaces between the attribute name and the next equals sign
if (endOfAttr(d,i))
{
//if the attribute is allowed, add it to the output
if (ae(attributen, aattr[tagname]))
tag += attribute;
attribute = '';
attributen = '';
attributeequals = false;
attributequotes = '';
}
expected = 'tag';
}
}
//if an attribute value is expected
else if (expected == 'attributev')
{
attribute += c;
//lookahead for end of value
if ((c == attributequotes) || ((n == ' ' || n == '/' || n == '>') && !attributequotes))
{
//if the attribute is allowed, add it to the output
if (ae(attributen, aattr[tagname]))
tag += attribute;
attribute = '';
attributen = '';
attributeequals = false;
attributequotes = '';
expected = 'tag';
}
}
//***Section for when the character is unknown but it is inside of a tag
else if (expected == 'tag')
{
//if its a space
if (c == ' ')
tag += c;
//if its a slash after the tagname, signalling a single tag.
else if (c == '/' && tagname)
{
tag += c;
tagtype = 'single';
}
//if its a slash before the tagname, signalling its an end tag
else if (c == '/')
{
tag += c;
tagtype = 'end';
}
//if its the end of a tag
else if (c == '>')
{
tag += c;
//if the tag is allowed, add it to the output
if (ae(tagname, tags))
o += tag;
//if its a start tag
if (tagtype == 'start')
{
//if the tag is supposed to have its contents deleted
if (ae(tagname, dctags))
{
//if there is an end tag, skip to it in order to delete the tags contents
if (-1 != (endpos = d.indexOf('</' + tagname, i)))
{
//have to make it one less because i gets incremented at the end of the loop
i = endpos-1;
}
//if there isn't an end tag, then it was probably a non-compliant single tag
}
}
tag = '';
tagname = '';
tagtype = 'start';
expected = '';
}
//if its an attribute name
else if (tagname && !attributen)
{
attributen += c.toLowerCase();
expected = 'attributen';
//lookahead for end of attribute name, in case its a one character attribute name
if (n == ' ' || n == '>' || n == '/' || n == '=')
{
attribute += attributen;
//check to see if its an attribute without an assigned value
//determines whether there is anything but spaces between the attribute name and the next equals sign
if (endOfAttr(d,i))
{
//if the attribute is allowed, add it to the output
if (ae(attributen, attributen))
tag += attribute;
attribute = '';
attributen = '';
attributeequals = false;
attributequotes = '';
}
expected = 'tag';
}
}
//if its a start quote for an attribute value
else if (ae(c, quotes) && attributeequals)
{
attribute += c;
attributequotes = c;
expected = 'attributev';
}
//if its an attribute value
else if (attributeequals)
{
attribute += c;
expected = 'attributev';
//lookahead for end of value, in case its only one character
if ((c == attributequotes) || ((n == ' ' || n == '/' || n == '>') && !attributequotes))
{
//if the attribute is allowed, add it to the output
if (ae(attributen, attributen))
tag += attribute;
attribute = '';
attributen = '';
attributeequals = false;
attributequotes = '';
expected = 'tag';
}
}
//if its an attribute equals
else if (c == '=' && attributen)
{
attribute += c;
attributeequals = true;
}
//if its the tagname
else
{
tagname += c.toLowerCase();
expected = 'tagname';
//lookahead for end of tag name, in case its a one character tag name
if (n == ' ' || n == '>' || n == '/')
{
tag += tagname;
expected = 'tag';
}
}
}
//if nothing is expected
else
{
//if its the start of a tag
if (c == '<')
{
tag = c;
expected = 'tag';
}
//anything else
else
o += c;
}
}
//beautifying regexs
//adding linebreaks tag
o = o.replace(/<html>/gi, "<html>");
//remove duplicate spaces
o = o.replace(/\s+([^!])/g, ' $1');
//remove unneeded spaces in tags
o = o.replace(/\s>/g, '>');
//remove empty tags
//this loops until there is no change from running the regex
var remptys = rempty.join('|');
var oo = o;
while ((o = o.replace(new RegExp("\\s?<(" + remptys + ")>\s*<\\/\\1>", 'gi'), '')) != oo)
oo = o;
//remove <a> tags
o = o.replace(/<A>(.*?)<\/A>/gi, "$1");
//make block tags regex string
var btagss = btags.join('|');
//add newlines after block tags
o = o.replace(new RegExp("\\s?</(" + btagss+ ")>", 'gi'), "</$1>\n");
//remove spaces before block tags, and add newline
o = o.replace(new RegExp("\\s*<(" + btagss + ")", 'gi'), "\n<$1");
//remove tags within heading tags
oo = o;
while ((o = o.replace(/<h([12345])>([^<]*)<([B-Z][A-Z0-1]*)\b[^>]*>([^<]*)<\/\3>([^<]*)<\/h\1>/gi, "<h$1>$2$4$5</h$1>")) != oo)
oo = o;
//remove tags within links
oo = o;
while ((o = o.replace(/<a href([^>]*)>([^<]*)<([B-Z][A-Z0-1]*)\b[^>]*>([^<]*)<\/\3>([^<]*)<\/a>/gi, "<a href$1>$2$4$5</a>")) != oo)
oo = o;
//fix lists
o = o.replace(/((<p.*>\s*(·|▪|§) .*<\/p.*>\n)+)/gi, "<ul>\n$1</ul>\n");//make ul for dot lists
// o = o.replace(/((<p.*>\s*\d+\S*\. .*<\/p.*>\n)+)/gi, "<ol>\n$1</ol>\n");//make ol for numerical lists
// o = o.replace(/((<p.*>\s*[a-z]+\S*\. .*<\/p.*>\n)+)/gi, "<ol style=\"list-style-type: lower-latin;\">\n$1</ol>\n");//make ol for latin lists
// o = o.replace(/<p(.*)>\s*(·|▪|§|\d+(\S*)\.|[a-z]+\S*\.) (.*)<\/p(.*)>\n/gi, "\t<li$1>$3$4</li$5>\n");//make li
o = o.replace(/<p(.*)>\s*(·|▪|§) (.*)<\/p(.*)>\n/gi, "\t<li$1>$3$4</li$5>\n");//make li
//extend outer lists around the nesting lists
o = o.replace(/<\/(ul|ol|ol style="list-style-type: lower-latin;")>\n(<(?:ul|ol|ol style="list-style-type: lower-latin;")>[\s\S]*<\/(?:ul|ol|ol style="list-style-type: lower-latin;")>)\n(?!<(ul|ol|ol style="list-style-type: lower-latin;")>)/g, "</$1>\n$2\n<$1>\n</$1>\n");
//nesting lists
o = o.replace(/<\/li>\s+<\/ol>\s+<ul>([\s\S]*?)<\/ul>\s+<ol>/g, "\n<ul>$1</ul></li>");//ul in ol
o = o.replace(/<\/li>\s+<\/ol>\s+<ol style="list-style-type: lower-latin;">([\s\S]*?)<\/ol>\s+<ol>/g, "\n<ol style=\"list-style-type: lower-latin;\">$1</ol></li>");//latin in ol
o = o.replace(/<\/li>\s+<\/ul>\s+<ol>([\s\S]*?)<\/ol>\s+<ul>/g, "\n<ol>$1</ol></li>");//ol in ul
o = o.replace(/<\/li>\s+<\/ul>\s+<ol style="list-style-type: lower-latin;">([\s\S]*?)<\/ol>\s+<ul>/g, "\n<ol style=\"list-style-type: lower-latin;\">$1</ol></li>");//latin in ul
o = o.replace(/<\/li>\s+<\/ol>\s+<ol style="list-style-type: lower-latin;">([\s\S]*?)<\/ol>\s+<ol>/g, "\n<ol style=\"list-style-type: lower-latin;\">$1</ol></li>");//ul in latin
o = o.replace(/<\/li>\s+<\/ul>\s+<ol style="list-style-type: lower-latin;">([\s\S]*?)<\/ol>\s+<ul>/g, "\n<ol style=\"list-style-type: lower-latin;\">$1</ol></li>");//ul in latin
//remove empty tags. this is needed a second time to delete empty lists that were created to fix nesting, but weren't needed
o = o.replace(new RegExp("\\s?<(" + remptys + ")>\s*<\\/\\1>", 'gi'), '');
//wikify it
o = o.replace(/<a href="(##)?#*([^>]*)">([^<]*)<\/a>/gi,"[[$3|$2$1]]");
o = o.replace(/(\n)*<h1>([^<]*)<\/h1>(\n)*/gi,"\n!$2\n");
o = o.replace(/(\n)*<h2>([^<]*)<\/h2>(\n)*/gi,"\n!!$2\n");
o = o.replace(/(\n)*<h3>([^<]*)<\/h3>(\n)*/gi,"\n!!!$2\n");
o = o.replace(/(\n)*<h4>([^<]*)<\/h4>(\n)*/gi,"\n!!!!$2\n");
o = o.replace(/(\n)*<h5>([^<]*)<\/h5>(\n)*/gi,"\n!!!!!$2\n");
return o;
}
//array equals
//loops through all the elements of an array to see if any of them equal the test.
function ae (needle, haystack)
{
if (typeof(haystack) == 'object')
for (var i = 0; i < haystack.length; i++)
if (needle == haystack[i])
return true;
return false;
}
//get character
//return specified character from d
function getc (d,i)
{
return d.charAt(i);
}
//end of attr
//determines if their is anything but spaces between the current character, and the next equals sign
function endOfAttr (d,i)
{
var between = d.substring(i+1, d.indexOf('=', i+1));
if (between.replace(/\s+/g, ''))
return true;
else
return false;
}
//}}}
/***
|Name|ConfirmNewTagsPlugin|
|Description|Enables wiki administrators to control creation of new tags|
|Version|0.1|
|Date|2010-06-08|
|Source|http://jos.tiddlyspot.com/#ConfirmNewTagPlugin|
|Author|Jonathan Overett Somnier|
|Overrides|config.commands.saveTiddler|
!!!!!Documentation
Add a non-existing tag to a tiddler and you will be asked to confirm this is your intention.
!!!!!Configuration
<<option chkConfirmNewTag>> Require confirmation of creation of a new tag
<<option chkPreventNewTag>> Prevent creation of new tags (ticking this overrides the confirmation option)
!!!!!Code
***/
//{{{
if (!config.options.chkConfirmNewTag)
config.options.chkConfirmNewTag=false; // default to standard
if (!config.options.chkPreventNewTag)
config.options.chkPreventNewTag=false; // default to standard
var _saveTiddler = config.commands.saveTiddler.handler;
config.commands.saveTiddler.handler = function(event,src,title) {
var flag = 1;
if (config.options.chkConfirmNewTag || config.options.chkPreventNewTag) {
var tiddlerElem = story.getTiddler(title);
if(tiddlerElem) {
var fields = {};
story.gatherSaveFields(tiddlerElem,fields);
tags = fields.tags.readBracketedList();
for (var i=0;i<tags.length;i++) {
if (!store.getTaggedTiddlers(tags[i]).length) {
if (config.options.chkPreventNewTag) {
alert("'"+tags[i]+"' is not an existing tag. Please only use existing tags, or speak to a wiki editor to create a new tag.");
flag = 0;
}
else {
flag = confirm("'"+tags[i]+"' is not an existing tag. Please use an existing tag or speak to a wiki editor before creating a new tag.\n\nAre you sure you want to create a new tag?");
}
if (flag == 0) break;
}
}
}
}
if (flag==1) return _saveTiddler.apply(this, arguments);
return false;
};
//}}}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|© 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description
Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.
''Syntax:''
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].
!Revision history
* v1.0.8 (2007-04-12)
** Adapted to latest TiddlyWiki 2.2 Beta importTiddlyWiki API (introduced with changeset 2004). TiddlyWiki 2.2 Beta builds prior to changeset 2004 are no longer supported (but TiddlyWiki 2.1 and earlier, of cause)
* v1.0.7 (2007-03-28)
** Also support "pre" formatted TiddlyWikis (introduced with TW 2.2) (when using "in" clause to work on external tiddlers)
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features:
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen)
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features:
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs:
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features:
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// ForEachTiddlerPlugin
//============================================================================
//============================================================================
// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {
if (!window.abego) window.abego = {};
version.extensions.ForEachTiddlerPlugin = {
major: 1, minor: 0, revision: 8,
date: new Date(2007,3,12),
source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};
// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
TiddlyWiki.prototype.forEachTiddler = function(callback) {
for(var t in this.tiddlers) {
callback.call(this,t,this.tiddlers[t]);
}
};
}
//============================================================================
// forEachTiddler Macro
//============================================================================
version.extensions.forEachTiddler = {
major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
config.macros.forEachTiddler = {
// Standard Properties
label: "forEachTiddler",
prompt: "Perform actions on a (sorted) selection of tiddlers",
// actions
actions: {
addToList: {},
write: {}
}
};
// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler
// ---------------------------------------------------------------------------
config.macros.forEachTiddler.getContainingTiddler = function(e) {
while(e && !hasClass(e,"tiddler"))
e = e.parentNode;
var title = e ? e.getAttribute("tiddler") : null;
return title ? store.getTiddler(title) : null;
};
config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);
if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the "in" clause
var tiddlyWikiPath = undefined;
if ((i < params.length) && params[i] == "in") {
i++;
if (i >= params.length) {
this.handleError(place, "TiddlyWiki path expected behind 'in'.");
return;
}
tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the where clause
var whereClause ="true";
if ((i < params.length) && params[i] == "where") {
i++;
whereClause = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the sort stuff
var sortClause = null;
var sortAscending = true;
if ((i < params.length) && params[i] == "sortBy") {
i++;
if (i >= params.length) {
this.handleError(place, "sortClause missing behind 'sortBy'.");
return;
}
sortClause = this.paramEncode(params[i]);
i++;
if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
sortAscending = params[i] == "ascending";
i++;
}
}
// Parse the script
var scriptText = null;
if ((i < params.length) && params[i] == "script") {
i++;
scriptText = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the action.
// When we are already at the end use the default action
var actionName = "addToList";
if (i < params.length) {
if (!config.macros.forEachTiddler.actions[params[i]]) {
this.handleError(place, "Unknown action '"+params[i]+"'.");
return;
} else {
actionName = params[i];
i++;
}
}
// Get the action parameter
// (the parsing is done inside the individual action implementation.)
var actionParameter = params.slice(i);
// --- Processing ------------------------------------------
try {
this.performMacro({
place: place,
inTiddler: tiddler,
whereClause: whereClause,
sortClause: sortClause,
sortAscending: sortAscending,
actionName: actionName,
actionParameter: actionParameter,
scriptText: scriptText,
tiddlyWikiPath: tiddlyWikiPath});
} catch (e) {
this.handleError(place, e);
}
};
// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {
var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);
var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
context["tiddlyWiki"] = tiddlyWiki;
// Get the tiddlers, as defined by the whereClause
var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
context["tiddlers"] = tiddlers;
// Sort the tiddlers, when sorting is required.
if (parameter.sortClause) {
this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
}
return {tiddlers: tiddlers, context: context};
};
// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
return this.getTiddlersAndContext(parameter).tiddlers;
};
// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
//
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
//
// All properties are optional.
// For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
var tiddlersAndContext = this.getTiddlersAndContext(parameter);
// Perform the action
var actionName = parameter.actionName ? parameter.actionName : "addToList";
var action = config.macros.forEachTiddler.actions[actionName];
if (!action) {
this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
return;
}
var actionHandler = action.handler;
actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};
// ---------------------------------------------------------------------------
// The actions
// ---------------------------------------------------------------------------
// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
return;
}
// Perform the action.
var list = document.createElement("ul");
place.appendChild(list);
for (var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var listItem = document.createElement("li");
list.appendChild(listItem);
createTiddlyLink(listItem, tiddler.title, true);
}
};
abego.parseNamedParameter = function(name, parameter, i) {
var beginExpression = null;
if ((i < parameter.length) && parameter[i] == name) {
i++;
if (i >= parameter.length) {
throw "Missing text behind '%0'".format([name]);
}
return config.macros.forEachTiddler.paramEncode(parameter[i]);
}
return null;
}
// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
if (p >= parameter.length) {
this.handleError(place, "Missing expression behind 'write'.");
return;
}
var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
// Parse the "begin" option
var beginExpression = abego.parseNamedParameter("begin", parameter, p);
if (beginExpression !== null)
p += 2;
var endExpression = abego.parseNamedParameter("end", parameter, p);
if (endExpression !== null)
p += 2;
var noneExpression = abego.parseNamedParameter("none", parameter, p);
if (noneExpression !== null)
p += 2;
// Parse the "toFile" option
var filename = null;
var lineSeparator = undefined;
if ((p < parameter.length) && parameter[p] == "toFile") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
return;
}
filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
p++;
if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
return;
}
lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
}
}
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
return;
}
// Perform the action.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
var count = tiddlers.length;
var text = "";
if (count > 0 && beginExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
for (var i = 0; i < count; i++) {
var tiddler = tiddlers[i];
text += func(tiddler, context, count, i);
}
if (count > 0 && endExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);
if (count == 0 && noneExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
if (filename) {
if (lineSeparator !== undefined) {
lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
text = text.replace(/\n/mg,lineSeparator);
}
saveFile(filename, convertUnicodeToUTF8(text));
} else {
var wrapper = createTiddlyElement(place, "span");
wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
}
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
return {
place : placeParam,
whereClause : whereClauseParam,
sortClause : sortClauseParam,
sortAscending : sortAscendingParam,
script : scriptText,
actionName : actionNameParam,
actionParameter : actionParameterParam,
tiddlyWikiPath : tiddlyWikiPathParam,
inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
};
};
// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
if (!idPrefix) {
idPrefix = "store";
}
var lenPrefix = idPrefix.length;
// Read the content of the given file
var content = loadFile(this.getLocalPath(path));
if(content === null) {
throw "TiddlyWiki '"+path+"' not found.";
}
var tiddlyWiki = new TiddlyWiki();
// Starting with TW 2.2 there is a helper function to import the tiddlers
if (tiddlyWiki.importTiddlyWiki) {
if (!tiddlyWiki.importTiddlyWiki(content))
throw "File '"+path+"' is not a TiddlyWiki.";
tiddlyWiki.dirty = false;
return tiddlyWiki;
}
// The legacy code, for TW < 2.2
// Locate the storeArea div's
var posOpeningDiv = content.indexOf(startSaveArea);
var posClosingDiv = content.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
throw "File '"+path+"' is not a TiddlyWiki.";
}
var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
// Create a "div" element that contains the storage text
var myStorageDiv = document.createElement("div");
myStorageDiv.innerHTML = storageText;
myStorageDiv.normalize();
// Create all tiddlers in a new TiddlyWiki
// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
var store = myStorageDiv.childNodes;
for(var t = 0; t < store.length; t++) {
var e = store[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
title = e.id.substr(lenPrefix);
if(title && title !== "") {
var tiddler = tiddlyWiki.createTiddler(title);
tiddler.loadFromDiv(e,title);
}
}
tiddlyWiki.dirty = false;
return tiddlyWiki;
};
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
//
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
var script = context["script"];
var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
var fullText = (script ? script+";" : "")+functionText+";theFunction;";
return eval(fullText);
};
// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
var result = [];
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
tiddlyWiki.forEachTiddler(function(title,tiddler) {
if (func(tiddler, context, undefined, undefined)) {
result.push(tiddler);
}
});
return result;
};
// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
var message = "Extra parameter behind '"+actionName+"':";
for (var i = firstUnusedIndex; i < parameter.length; i++) {
message += " "+parameter[i];
}
this.handleError(place, message);
};
// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? -1
: +1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? +1
: -1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
// To avoid evaluating the sortClause whenever two items are compared
// we pre-calculate the sortValue for every item in the array and store it in a
// temporary property ("forEachTiddlerSortValue") of the tiddlers.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
var count = tiddlers.length;
var i;
for (i = 0; i < count; i++) {
var tiddler = tiddlers[i];
tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
}
// Do the sorting
tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);
// Delete the temporary property that holds the sortValue.
for (i = 0; i < tiddlers.length; i++) {
delete tiddlers[i].forEachTiddlerSortValue;
}
};
// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
displayMessage(message);
};
// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
var message ="<<"+macroName;
for (var i = 0; i < params.length; i++) {
message += " "+params[i];
}
message += ">>";
displayMessage(message);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};
// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
if (place) {
this.createErrorElement(place, exception);
} else {
throw exception;
}
};
// Internal.
//
// Encodes the given string.
//
// Replaces
// "$))" to ">>"
// "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
var reGTGT = new RegExp("\\$\\)\\)","mg");
var reGT = new RegExp("\\$\\)","mg");
return s.replace(reGTGT, ">>").replace(reGT, ">");
};
// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
//
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
// Remove any location part of the URL
var hashPos = originalPath.indexOf("#");
if(hashPos != -1)
originalPath = originalPath.substr(0,hashPos);
// Convert to a native file format assuming
// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
var localPath;
if(originalPath.charAt(9) == ":") // pc local file
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(7));
else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(5));
else // pc network file
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
return localPath;
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
"forEachTiddler");
//============================================================================
// End of forEachTiddler Macro
//============================================================================
//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
var n = prefix.length;
return (this.length >= n) && (this.slice(0, n) == prefix);
};
//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
var n = suffix.length;
return (this.length >= n) && (this.right(n) == suffix);
};
//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
return this.indexOf(substring) >= 0;
};
//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] == item) {
return i;
}
}
return -1;
};
//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false.
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
return (this.indexOf(item) >= 0);
};
//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
for(var i = 0; i < items.length; i++) {
if (this.contains(items[i])) {
return true;
}
}
return false;
};
//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
//
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null]
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
for(var i = 0; i < items.length; i++) {
if (!this.contains(items[i])) {
return false;
}
}
return true;
};
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink,
displayMessage, endSaveArea, hasClass, loadFile, saveFile,
startSaveArea, store, wikify */
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The ~HTMLFormatting plugin allows you to ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2009.01.05 [2.4.0] in wikifyTextNodes(), pass w.highlightRegExp and w.tiddler to wikify() so that search term highlighting and tiddler-relative macro processing will work
| see [[HTMLFormattingPluginInfo]] for additional revision details |
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormattingPlugin= {major: 2, minor: 4, revision: 0, date: new Date(2009,1,5)};
// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
if (i<config.formatters.length) config.formatters[i].handler=function(w) {
if (!this.lookaheadRegExp) // fixup for TW2.0.x
this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var html=lookaheadMatch[1];
// if <nowiki> is present, just let browser handle it!
if (html.indexOf('<nowiki>')!=-1)
createTiddlyElement(w.output,"span").innerHTML=html;
else {
// if <hide linebreaks> is present, suppress wiki-style literal handling of newlines
if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n([^!])/g,' $1');
// 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,w.highlightRegExp,w.tiddler);
break;
default:
for (var i=0;i<theNode.childNodes.length;i++)
wikifyTextNodes(theNode.childNodes.item(i),w); // recursion
break;
}
}
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|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:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
|!Plugin|!Description|
|CleanTiddlerPlugin|<<tiddler [[CleanTiddlerPlugin::Description]]>>|
|ConfirmNewTagPlugin|<<tiddler [[ConfirmNewTagPlugin::Description]]>>|
|PrintButton|<<tiddler [[PrintButton::Description]]>>|
|ReloadMacro|<<tiddler [[ReloadMacro::Description]]>>|
|SaveMinorEditPlugin|<<tiddler [[SaveMinorEditPlugin::Description]]>>|
|TiddlyLockCheckMacro|<<tiddler [[TiddlyLockCheckMacro::Description]]>>|
|TiddlyLockPluginUnlockMacro|<<tiddler [[TiddlyLockPluginUnlockMacro::Description]]>>|
|ZHandbookReferencePlugin|<<tiddler [[ZHandbookReferencePlugin::Description]]>>|
Read the [[tiddlywiki.org entry on plugins|http://tiddlywiki.org/wiki/Plugins]] for information on how to install these plugins in your TiddlyWiki.
<<tag systemConfig Plugins>>
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
/***
|Name|PrintButton|
|Description|Add print button for use on tiddler toolbar|
|Version|1.0|
|Author|Jonathan Overett Somnier|
|Source|http://jos.tiddlyspot.com/#PrintButton|
***/
//{{{
config.commands.printTiddler = {
text: "print",
tooltip: "Print this article"
};
config.commands.printTiddler.handler = function() {
window.print();
return false;
};
//}}}
/***
|Name|ReloadMacro|
|Description|Macro to provide button for reloading the wiki|
|Version|1.0|
|Author|Jonathan Overett Somnier|
|Source|http://jos.tiddlyspot.com/#ReloadMacro|
!!!!!Documentation
Adding """<<reload>>""" to a tiddler will display a 'reload' button which when clicked on will try to reload the Tiddlywiki (with the usual prompt to save the wiki if it contains unsaved changes).
!!!!!Code
***/
//{{{
config.macros.reload={};
config.macros.reload.handler= function(place,macroName,params,wikifier,paramString,tiddler)
{
var label = params[0]||"reload";
var tooltip = params[1]||"Reload wiki";
createTiddlyButton(place,label,tooltip,this.onclick);
};
config.macros.reload.onclick= function()
{
window.location.reload( true );
return false;
};
//}}}
/***
|Name|SaveMinorEditPlugin|
|Source|http://jos.tiddlyspot.com/#SaveMinorEditPlugin|
|Version|1.1|
|Author|Jonathan Overett Somnier|
|License||
|~CoreVersion|2.1|
|Description|Creates a toolbar command to make it easier to edit tiddlers without updating their 'modified' date|
!!!!!Documentation
Amend your ToolbarCommands 'EditToolbar' row to include 'saveTiddlerMinorEdit'. This creates a 'minor edit' button which will be shown when editing tiddlers. Clicking on that button has the same effect as clicking on the 'done' button, except the 'modified' date of the tiddler is left unchanged so macros such as """<<timeline>>""" will not show the tiddler as having been updated.
SaveMinorEditPlugin recognises where ConfirmNewTagsPlugin is being used so control over creation of tags is maintained whether 'done' or 'minor edit' is used to complete a tiddler edit.
!!!!!Code
***/
//{{{
config.commands.saveTiddlerMinorEdit = {
text: "minor edit",
tooltip: "Save changes to this article without updating the list of modified articles",
hideReadOnly: "true"
};
config.commands.saveTiddlerMinorEdit.handler = function(event,src,title)
{
var flag = 1;
if (config.options.chkConfirmNewTag || config.options.chkPreventNewTag) {
var tiddlerElem = story.getTiddler(title);
if(tiddlerElem) {
var fields = {};
story.gatherSaveFields(tiddlerElem,fields);
tags = fields.tags.readBracketedList();
for (var i=0;i<tags.length;i++) {
if (!store.getTaggedTiddlers(tags[i]).length) {
if (config.options.chkPreventNewTag) {
alert("'"+tags[i]+"' is not an existing tag. Please only use existing tags, or speak to a wiki editor to create a new tag.");
flag = 0;
}
else {
flag = confirm("'"+tags[i]+"' is not an existing tag. Please use an existing tag or speak to a wiki editor before creating a new tag.\n\nAre you sure you want to create a new tag?");
}
if (flag == 0) break;
}
}
}
}
if (flag==1) {
var newTitle = story.saveTiddler(title,true);
if(newTitle)
story.displayTiddler(null,newTitle);
}
return false;
};
//}}}
/***
|Name|TiddlyLockCheckMacro|
|Description|Macros to display whether wiki is locked by [[TiddlyLockPlugin|http://www.minormania.com/tiddlylock/tiddlylock.html]]|
|Version|1.0|
|Author|Jonathan Overett Somnier|
|Requires|TiddlyLockPlugin|
|Source|http://jos.tiddlyspot.com/#TiddlyLockCheckMacro|
!!!!!Documentation
TiddlyLockCheckMacro provides two macros that can be used to indicate to users whether the Tiddlywiki is currently locked for editing by [[TiddlyLockPlugin|http://www.minormania.com/tiddlylock/tiddlylock.html]].
"""<<tiddlyLockCheck>>""" provides a button which, when clicked on, displays a message regarding the wiki's state (ie whether a user is free to edit the wiki, whether it is currently being edited by another user, or is has been edited by someone else and so needs reloading before it can be edited).
"""<<tiddlyLockCheck>>""" displays the status directly. If combined with InlineJavascriptPlugin this can be automatically refreshed periodically to give a reasonably up-to-date indication of the wiki's status (see TiddlyLockStatus for such a script). The status message is colour-coded (red: being edited, amber: you have locked the wiki for editing, green: wiki is free to be edited (with a reload button shown if appropriate)).
!!!!!Examples
"""<<tiddlyLockCheck>>"""
<<tiddlyLockCheck>>
"""<<tiddlyLockStatus>>"""
<<tiddlyLockStatus>>
!!!!!Code
***/
//{{{
config.macros.tiddlyLockCheck={};
config.macros.tiddlyLockCheck.handler= function(place,macroName,params,wikifier,paramString,tiddler)
{
var label = params[0]||"Wiki status";
var tooltip = params[1]||"Check whether wiki is locked for editing";
createTiddlyButton(place,label,tooltip,this.onclick);
};
config.macros.tiddlyLockCheck.onclick= function()
{
if(TLIsLocked() && !TLIsLockedByMe())
{
if(TLLockedBy(TiddlyLock.LockData))
{
displayMessage('The wiki is locked. It is being edited by '+TLLockedBy(TiddlyLock.LockData)+'.');
}
else
{
displayMessage(TiddlyLock.Msg.Changed+' It is available for editing. '+TiddlyLock.Msg.Reload);
}
}
if(TLIsLocked() && TLIsLockedByMe())
{
displayMessage('You are currently editing the wiki. It is locked so cannot be edited by others.');
}
if(!TLIsLocked())
{
displayMessage("The wiki is available for editing. Just double-click on an article to edit it, or use the 'edit' button.");
}
return false;
};
//}}}
//{{{
config.macros.tiddlyLockStatus={};
config.macros.tiddlyLockStatus.handler= function(place,macroName,params,wikifier,paramString,tiddler)
{
var status = "";
var color = "";
var reload = false;
if(TLIsLocked() && !TLIsLockedByMe())
{
if(TLLockedBy(TiddlyLock.LockData))
{
color = 'red';
status = 'Wiki locked by '+TLLockedBy(TiddlyLock.LockData);
}
else
{
color = 'green';
status = 'Reload wiki to edit';
reload = true;
}
}
if(TLIsLocked() && TLIsLockedByMe())
{
color = 'darkorange';
status = 'Wiki locked by you';
}
if(!TLIsLocked())
{
color = 'green';
status = 'Wiki can be edited';
}
wikify('@@background-color:' + color + ';{{TiddlyLockStatusText{' + (reload ? "<<reload \"" : "") + status + (reload ? "\">>" : "") + '}}}@@', place);
return false;
};
//}}}
/***
|Name|TiddlyLockPlugin|
|Source|http://www.minormania.com/tiddlylock/tiddlylock.html|
|Version|1.1.0|
|TiddlyWiki Core Version|2.5.0|
|Author|Richard Hobbis|
|License|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|Type|plugin|
|Overrides|config.macros.newTiddler.onClickNewTiddler(), config.commands.cancelTiddler.handler(), config.commands.deleteTiddler.handler, config.commands.editTiddler.handler(), config.commands.saveTiddler.handler(), saveChanges(), checkUnsavedChanges()|
|Description|Automatically locks and unlocks the TiddlyWiki as required, allowing multiple users to edit the TiddlyWiki without fear of overwriting other users' changes.|
!!!Usage
<<<
Simply import TiddlyLockPlugin into your TiddlyWiki!
<<<
!!!Installation
<<<
Import (or copy/paste) ''this tiddler'' into your TiddlyWiki and make sure it's tagged with <<tag systemConfig>>. Reload your TiddlyWiki to enable TiddlyLock.
<<<
!!!Configuration
<<<
None required!
<<<
!!!Revision History
<<<
''2009.05.28 [1.1.0]'' Upgraded this file to TiddlyWiki core version 2.5.0.
''2007.06.22 [1.0.4]'' Added locking on 'new tiddler' which also traps 'new journal'. Tweaked messages.
''2007.06.20 [1.0.3]'' Fixed an issue that occurred when a user navigated away from the TiddlyWiki without saving outstanding changes.
''2007.05.10 [1.0.2]'' Implemented a timestamp to track the last update time. This fixes the multi-browser edit issue and also removes the need for a password.
''2007.05.08 [1.0.1]'' Function overrides are now done using apply() ensuring clean upgrades (thanks Martin!)
''2007.05.01 [1.0.0]'' Initial Release
<<<
!!!Known Issues
<<<
*Monkey Pirate TiddlyWiki (MPTW) adds a ''disable'' button to the toolbar for systemConfig tiddlers. This button is available even when the TW is marked as readOnly and therefore it's possible for two users to disable/enable plugins at the same time. In this case, whoever saves the TW last will 'win' and their changes will be saved. Note that this is only an issue if there are no other unsaved changes in both browsers - TiddlyLock still handles all other changes.
<<<
!!!Credits
<<<
This feature was developed by Richard Hobbis (rhobbis [at] hotmail [dot] com).
<<<
!!!Code
***/
//{{{
// Convert a date to UTC YYYYMMDDHHMMSSMMM string format
// This is the same as the builtin function convertToYYYYMMDDHHMMSSMMM() but
// without the '.' in the middle - this allows simple date comparisons
Date.prototype.TLConvertToYYYYMMDDHHMMSSMMM = function()
{
return(String.zeroPad(this.getUTCFullYear(),4)
+ String.zeroPad(this.getUTCMonth()+1,2)
+ String.zeroPad(this.getUTCDate(),2)
+ String.zeroPad(this.getUTCHours(),2)
+ String.zeroPad(this.getUTCMinutes(),2)
+ String.zeroPad(this.getUTCSeconds(),2)
+ String.zeroPad(this.getUTCMilliseconds(),4));
}
// namespace for TiddlyLock
TiddlyLock = {};
// Load/Last Update timestamp
TiddlyLock.TimeStamp = new Date().TLConvertToYYYYMMDDHHMMSSMMM();
// Lockfile
TiddlyLock.LockPath = '';
TiddlyLock.OldLockData = '';
TiddlyLock.LockData = '';
// define messages
TiddlyLock.Msg = {
Locked: 'File locked',
Unlocked: 'File unlocked',
LockFailed: 'Failed to lock file',
UnlockFailed: 'Failed to unlock file',
ReadOnly: 'Now in Read-Only mode.',
Changed: 'This file has been changed by someone else.',
Reload: 'Reload this file before editing.'};
// create/update the lock file
function TLSave(timeStamp,lockedBy)
{
var lockedText='';
if (lockedBy!='')
{
lockedText=timeStamp+'##'+lockedBy;
}
else lockedText=timeStamp+'##';
var lockSave=saveFile(TiddlyLock.LockPath,lockedText);
TiddlyLock.TimeStamp = timeStamp;
return false;
}
// Create/update the lock file to prevent other users from editing the TW
function TLLock()
{
clearMessage();
lockSave = TLSave(new Date().TLConvertToYYYYMMDDHHMMSSMMM(),config.options.txtUserName);
displayMessage(TiddlyLock.Msg.Locked,'');
return false;
}
// Clear the lock file if necessary, but only if I have it locked, setting the
// timestamp in the lockfile to the specified value
function TLUnlock(timeStamp)
{
if ((store && store.isDirty && !store.isDirty())
&& (story && story.areAnyDirty && !story.areAnyDirty())
&& TLIsLocked()
&& TLIsLockedByMe())
{
lockSave=TLSave(timeStamp,'','');
displayMessage(TiddlyLock.Msg.Unlocked,'');
TiddlyLock.OldLockData = TiddlyLock.LockData;
}
return false;
}
// Get the contents of the lock file, if it exists
function TLLockPath()
{
var lockPath,p;
var originalPath=document.location.toString();
var localPath=getLocalPath(originalPath);
if((p=localPath.lastIndexOf('.')) != -1)
lockPath=localPath.substr(0,p) + '.lck';
else lockPath=localPath + '.lck';
return lockPath;
}
// Get the contents of the lock file, if it exists
function TLLockData()
{
TiddlyLock.LockPath = TLLockPath();
return loadFile(TiddlyLock.LockPath);
}
// Get the contents of the lock file, if it exists
function TLIsLocked()
{
TiddlyLock.LockData = TLLockData();
if (TiddlyLock.LockData
&& ( TLLockedBy(TiddlyLock.LockData)!='' // someone has it locked
|| TiddlyLock.TimeStamp < TLLockedTimeStamp(TiddlyLock.LockData) // changed by someone else but not currently locked
)
)
return true;
else
return false;
}
// check if locked by me
function TLIsLockedByMe()
{
if(TiddlyLock.LockData == TiddlyLock.TimeStamp+'##' + config.options.txtUserName)
return true;
else
return false;
}
// returns just the timestamp portion of the supplied lock file contents
function TLLockedTimeStamp(lockData)
{
if(lockData)
return lockData.split('##')[0];
else
return '';
}
// returns just the username portion of the supplied lock file contents
function TLLockedBy(lockData)
{
if(lockData)
return lockData.split('##')[1];
else
return '';
}
// display a message if locked or changed
function TLChangesAllowed()
{
if(TLIsLocked() && !TLIsLockedByMe())
{
// if(!readOnly)
{
readOnly=true;
if(TLLockedBy(TiddlyLock.LockData))
{
displayMessage(TiddlyLock.Msg.Locked+' by '+TLLockedBy(TiddlyLock.LockData));
alert(TiddlyLock.Msg.Locked+' by '+TLLockedBy(TiddlyLock.LockData)+'. '+TiddlyLock.Msg.ReadOnly);
}
else
{
displayMessage(TiddlyLock.Msg.Changed+' '+TiddlyLock.Msg.Reload);
alert(TiddlyLock.Msg.Changed+' '+TiddlyLock.Msg.Reload);
}
}
return false;
}
else
return true;
}
//*********************************************
// OVERRIDE STANDARD FUNCTIONS
//*********************************************
//
// OVERRIDE onClickNewTiddler()
//
TiddlyLock.onClickNewTiddler = config.macros.newTiddler.onClickNewTiddler;
config.macros.newTiddler.onClickNewTiddler = function(event,src,title)
{
if (TLChangesAllowed())
{
TiddlyLock.OldLockData = TiddlyLock.LockData;
TLLock();
var ret = TiddlyLock.onClickNewTiddler.apply(this,arguments);
return ret;
}
}
//
// OVERRIDE checkUnsavedChanges()
//
TiddlyLock.checkUnsavedChanges = checkUnsavedChanges;
checkUnsavedChanges = function(event,src,title)
{
var ret = TiddlyLock.checkUnsavedChanges.apply(this,arguments);
if(TLIsLocked() && TLIsLockedByMe())
lockSave=TLSave(TLLockedTimeStamp(TiddlyLock.OldLockData),'','');
return ret;
}
//
// OVERRIDE cancelTiddler()
//
TiddlyLock.cancelTiddler = config.commands.cancelTiddler.handler;
config.commands.cancelTiddler.handler = function(event,src,title)
{
var ret = TiddlyLock.cancelTiddler.apply(this,arguments);
TLUnlock(TLLockedTimeStamp(TiddlyLock.OldLockData));
return ret;
}
//
// OVERRIDE deleteTiddler()
//
TiddlyLock.deleteTiddler = config.commands.deleteTiddler.handler;
config.commands.deleteTiddler.handler = function(event,src,title)
{
if (TLChangesAllowed())
{
TiddlyLock.OldLockData = TiddlyLock.LockData;
TLLock();
var ret = TiddlyLock.deleteTiddler.apply(this,arguments);
return ret;
}
}
//
// OVERRIDE editTiddler()
//
TiddlyLock.editTiddler = config.commands.editTiddler.handler;
config.commands.editTiddler.handler = function(event,src,title)
{
if (TLChangesAllowed())
{
TiddlyLock.OldLockData = TiddlyLock.LockData;
TLLock();
}
var ret = TiddlyLock.editTiddler.apply(this,arguments);
return ret;
}
//
// OVERRIDE saveChanges()
//
TiddlyLock.saveChanges = saveChanges;
saveChanges = function(onlyIfDirty)
{
if(TLChangesAllowed())
{
var ret = TiddlyLock.saveChanges.apply(this,arguments);
TLUnlock(new Date().TLConvertToYYYYMMDDHHMMSSMMM());
return ret;
}
else
return false;
}
//
// OVERRIDE saveTiddler()
//
TiddlyLock.saveTiddler= config.commands.saveTiddler.handler;
config.commands.saveTiddler.handler=function(event,src,title)
{
var ret = TiddlyLock.saveTiddler.apply(this,arguments);
TLUnlock(new Date().TLConvertToYYYYMMDDHHMMSSMMM());
return ret;
}
//}}}
/***
|Name|TiddlyLockPluginUnlockMacro|
|Description|Macro for forcing TiddlyLockPlugin to unlock wiki|
|Version|1.0|
|Author|Jonathan Overett Somnier|
|Requires|TiddlyLockPlugin|
|Source|http://jos.tiddlyspot.com/#TiddlyLockPluginUnlockMacro|
***/
//{{{
//
// CREATE macro to unlock lock file
//
config.macros.tiddlyLockUnlock = {};
config.macros.tiddlyLockUnlock.handler= function(place,macroName,params,wikifier,paramString,tiddler)
{
var label = params[0]||"unlock";
var tooltip = params[1]||"Force wiki to be unlocked for editing";
createTiddlyButton(place,label,tooltip,this.onclick);
};
config.macros.tiddlyLockUnlock.onclick= function()
{
if (TLIsLocked())
{
lockSave=TLSave(new Date().TLConvertToYYYYMMDDHHMMSSMMM(),'','');
displayMessage(TiddlyLock.Msg.Unlocked + "\nPlease reload the wiki",'');
// TiddlyLock.OldLockData = TiddlyLock.LockData;
TiddlyLock.TimeStamp = 0;
}
else
{
displayMessage("Wiki is already unlocked",'');
}
return false;
}
// add 'update' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
config.tasks.unlockTask = {
text:"unlock",
tooltip:"Unlock wiki to make it available for editing",
content:"<<tiddlyLockUnlock>>"
}
config.backstageTasks.splice(config.backstageTasks.indexOf("tweak")+1,0,"unlockTask");
}
//}}}
<<tiddlyLockStatus>>
<script>
setTimeout("config.refreshers.content(document.getElementById('TiddlyLockStatus'))",30000);
</script>
|~ViewToolbar|closeTiddler closeOthers ! +editTiddler ! printTiddler ! > < * fields syncing permalink references jump|
|~EditToolbar|+saveTiddler saveTiddlerMinorEdit -cancelTiddler deleteTiddler|
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'jos';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 16/06/2010 13:38:19 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . | ok | ok |
| 16/06/2010 13:44:44 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 16/06/2010 13:48:09 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 16/06/2010 13:49:13 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 16/06/2010 23:56:13 | Jonathan | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 16/06/2010 23:57:16 | Jonathan | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 17/06/2010 00:04:03 | Jonathan | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . | ok |
| 17/06/2010 00:42:05 | Jonathan | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 17/06/2010 10:15:50 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
| 17/06/2010 10:16:56 | YourName | [[/|http://jos.tiddlyspot.com/]] | [[store.cgi|http://jos.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jos.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 3,
date: new Date("Feb 24, 2008"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
/***
|Name|HandbookReferencePlugin|
|Description|Converts references to FSA Handbook into links to the relevant part of the FSA Handbook website|
|Author|Jonathan Overett Somnier ( jonathan at overett dot net )|
|Source|http://jos.tiddlyspot.com/#ZHandbookReferencePlugin|
|Version|0.3|
|Date|16 June 2010|
|~CoreVersion|2.2.3|
!!!!!Documentation
Tiddlers containing a valid FSA Handbook reference will convert the reference into a link to the relevant part of the FSA Handbook website (http://fsahandbook.info).
!!!!!Examples
A few FSA Handbook links:
DISP
COBS 1
CASS 2.3
MCOB 2.3.4R
!!!!!Code
***/
//{{{
if (config.options.txtHandbookModules===undefined) config.options.txtHandbookModules="PRIN|SYSC|COND|APER|FIT|GEN|FEES|UPRU|GENPRU|BIPRU|INSPRU|MIPRU|PRU|COBS|COB|ICOBS|ICOB|MCOB|CASS|MAR|TC|ML|AUTH|SUP|ENF|DEPP|DEC|DISP|COMP|COAF|CIS|COLL|CRED|ECO|ELM|LLD|PROF|RCB|REC|LR|PR|DTR|EMPS|FREN|OMPS|SERV|BSOG|COLLG|EG|PERG|RPPD|UNFCOG|BCOBS|CRAG|FINMAR|BSOCS";
config.formatters.push({
name: "handbookreference",
match: "\\b(" + config.options.txtHandbookModules + ")\\b( [0-9]+[A-Z]*\\.?[0-9A-Z]?\\.?[0-9A-Za-z()]*)?",
lookaheadRegExp: new RegExp("\\b(" + config.options.txtHandbookModules + ")\\b( ([0-9]+[A-Z]*)\\.?([0-9A-Z]?))?","mg"),
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
var url = "http://fsahandbook.info/FSA/html/handbook/" + lookaheadMatch[1] + "/";
if (lookaheadMatch[3]) {
url += lookaheadMatch[3] + "/";
if (lookaheadMatch[4]) url += lookaheadMatch[4] + "/";
}
w.outputText(createExternalLink(w.output,url),w.matchStart,w.nextMatch);
}
});
//}}}