Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
|''Type:''|file|
|''URL:''|http://www.tiddlytools.com/|
|''Workspace:''|(default)|
This tiddler was automatically created to record the details of this server
/***
|Name|[[EditFieldPlugin]]|
|Source|http://www.TiddlyTools.com/#EditFieldPlugin|
|Version|1.6.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|extend core edit macro for use in ViewTemplates or direct embedding in tiddler content|
!!!!!Documentation
>see [[EditFieldPluginInfo]]
!!!!!Revisions
<<<
2011.04.10 1.6.2 fixed 'null' fieldname handling in Chrome
| Please see [[EditFieldPluginInfo]] for previous revision details |
2007.08.22 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.EditFieldPlugin= {major: 1, minor: 6, revision: 2, date: new Date(2011,4,10)};
config.macros.edit.editFieldPlugin_savedHandler=config.macros.edit.handler;
config.macros.edit.cancelMsg = "Abandon changes to %0@%1?";
config.macros.edit.saveMsg = "Save changes to %0@%1?";
config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// let core render input/textarea, then get resulting element
config.macros.edit.editFieldPlugin_savedHandler.apply(this,arguments);
var fieldType=params[0]=="text"||params[1]?'textarea':'input';
var elems=place.getElementsByTagName(fieldType); var e=elems[elems.length-1];
// extended fieldname@tiddlername handling
var parts=e.getAttribute("edit").split('@');
var field=parts[0];
var title=parts[1]||tiddler.title;
if (title=='here') title=tiddler.title;
// stop field from being saved with 'done' button
if (parts[1]) { e.removeAttribute("edit"); e.setAttribute("field",field); }
// save starting value and target tiddler
e.value=store.getValue(title,field)||e.value; // get field value
e.setAttribute("currval",e.value); // save starting value
e.setAttribute("tiddler",title);
// force height for textarea field
if (fieldType=="textarea" && params[1]) e.style.height=params[1]+"em";
// if viewing tiddler, add autosave handlers
var here=story.findContainingTiddler(place);
var isViewed=here&&here.getAttribute("template").indexOf("ViewTemplate")!=-1;
if (parts[1]||isViewed) { // remote reference or view mode editing...
story.setDirty(tiddler.title,false); // clear tiddler ("dirty") flag (set by core)
e.onkeydown=function(ev) { // ENTER key=save (for single-line input)
var event=ev?ev:window.event;
this.setAttribute("keyCode",event.keyCode); // save last keyCode (for blur)
if (event.keyCode==13 && this.nodeName.toUpperCase()!="TEXTAREA")
this.saveField(); // save input to tiddler field
}
e.onblur=function(ev) { // confirm input when focus moves away
var event=ev?ev:window.event;
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit")||this.getAttribute("field");
if (this.value==this.getAttribute("currval")) return; // no change
if (this.getAttribute("keyCode")=="27") { // if user pressed ESC
var msg=config.macros.edit.cancelMsg.format([field,tid]);
if (!msg.length || confirm(msg))
this.value=this.getAttribute("currval"); // reset value
this.id=new Date().getTime(); // unique ID for re-focus after blur
setTimeout("document.getElementById('"+this.id+"').focus()",1);
} else { // other focus change events
var msg=config.macros.edit.saveMsg.format([field,tid]);
if (!msg.length || confirm(msg)) this.saveField(); // save value
else this.value=this.getAttribute("currval");
}
};
e.saveField=function() { // unpack/validate attribs and then save the field
var tid=this.getAttribute("tiddler"); if (!tid || !tid.length) return;
var field=this.getAttribute("edit")||this.getAttribute("field");
var title=(field=="title")?this.value:tid;
if (!title.length) { // error: blank tiddler title
this.value=this.getAttribute("currval"); // reset value
this.id=new Date().getTime(); // unique ID for delayed messages/refocus
setTimeout("displayMessage('Please enter a non-blank value')",1);
setTimeout("document.getElementById('"+this.id+"').focus()",2);
return;
}
config.macros.edit.saveField(tid,title,field,this.value);
this.setAttribute("currval",this.value); // remember new starting value
};
}
}
//}}}
//{{{
// save input value to tiddler field (create/touch/rename tiddler as needed)
config.macros.edit.saveField = function(tid,title,field,val) {
var t=store.getTiddler(tid);
store.suspendNotifications();
var anim=config.options.chkAnimate; config.options.chkAnimate=false; // suspend animation
var who=t&&config.options.chkForceMinorUpdate?t.modifier:config.options.txtUserName;
var when=t&&config.options.chkForceMinorUpdate?t.modified:new Date();
store.saveTiddler(t?tid:title,title,t?t.text:"",who,when,t?t.tags:[],t?t.fields:null);
store.setValue(title,field,val); // save field
if (tid!=title) // new title... show renamed tiddler in place of current one
{ story.displayTiddler(story.getTiddler(tid),title); story.closeTiddler(tid); }
if (field=="text") // content changed, refresh tiddler display
{ story.refreshTiddler(title,null,true); }
config.options.chkAnimate=anim; // resume animation
store.resumeNotifications();
store.notify(title,true);
}
//}}}
/***
|Name|EditFieldPluginInfo|
|Source|http://www.TiddlyTools.com/#EditFieldPlugin|
|Documentation|http://www.TiddlyTools.com/#EditFieldPluginInfo|
|Version|1.6.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|documentation for EditFieldPlugin|
!!!!!Usage
<<<
When a tiddler is edited, input fields -- defined in the [[EditTemplate]] -- are displayed. The ''TiddlyWiki //template// syntax'' for the {{{<<edit>>}}} macro is:
{{{
<span class="editor" macro="edit fieldname numberOfLines defaultValue"></span>
}}}
*''fieldname''<br>refers to a tiddler field, either standard or custom, within the current tiddler.
*''numberOfLines'' //(optional, default=1)//<br>if omitted (or equal to 1), a standard one-line text input field is created. If >1, a multi-line //textarea// field is created. Note: the standard tiddler 'text' field has special core handling applied so that it is always rendered using a textarea field, whose size is based on the length of the tiddler content, limted by the {{{<<option txtMaxEditRows>>}}} setting.
*''defaultValue'' //(optional, default=blank)//<br>a fallback value to display if the field is not yet defined in the tiddler.
The TiddlyWiki core only supports use of the edit macro within an [[EditTemplate]] definition. Changes to values displayed in the tiddler editor are only saved (or discarded) if you press the "done" (or "cancel") command in the tiddler editor's toolbar. However, these commands are not available when //viewing// a tiddler, so there is no way to trigger the saving of any changes you have entered.
EditFieldPlugin adds handling that allows you to embed the edit macro in the [[ViewTemplate]] (using the standard ''TiddlyWiki //template// syntax'') or directly in tiddler content using ''TiddlyWiki //wiki// syntax'' (e.g, {{{<<edit fieldname@TiddlerName numberOfLines defaultValue>>}}}).
When you make changes to a tiddler input field displayed in //viewed// content, your changes are saved (or discarded) as soon as you press ENTER (or ESC). If you move away from that input field ('onBlur' handling), a message is displayed asking you to confirm saving/discarding any field changes. To suppress either (or both) of these confirmation messages, you can add the following configuration settings to [[EditFieldPluginConfig]] (tagged with <<tag systemConfig>>):
{{{
config.macros.edit.cancelMsg = "";
config.macros.edit.saveMsg = "";
}}}
The plugin also enhances the fieldname syntax to allow reference to fields in other tiddlers using: "{{{fieldname@TiddlerName}}}", so you can 'remotely' display and edit fields stored those tiddlers. This allows you to create, for example, a summary tiddler for reviewing/editing field values from several tiddlers at the same time.
<<<
!!!!!Examples
<<<
*"""<<edit foobar>>"""<br><<edit foobar>>
*"""<<edit foobar@SomeTiddler>>"""<br><<edit foobar@SomeTiddler>>
*"""<<edit tags>>"""<br><<edit tags>>
*"""<<edit text 15>>"""<br>{{editor{<<edit text 15>>}}}
<<<
!!!!!Revisions
<<<
2011.04.10 1.6.2 fixed 'null' fieldname handling in Chrome
2010.11.15 1.6.1 fixed display of field values for 'non-stored' tiddler content (e.g., shadows, tags, default new tiddler)
2010.10.31 1.6.0 fixed display of remote field values. In onblur(), refactored save/cancel message text for easier customization and bypass confirmation if text is blank.
2009.09.16 1.5.1 fixed 'onblur' handling for local fields (fieldname@here). Added support for '@here' syntax
2009.09.05 1.5.0 code refactored. added handling for fieldname@tiddlername
2007.08.22 1.0.0 initial release
<<<
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<div macro="editFields"></div>
<!--}}}-->
/***
|''Name''|EditTemplateFieldsPlugin|
|''Version''|0.4.6|
|''Status''|beta|
|''Author''|Jon Robson|
|''Description''|Provides editing of custom fields|
|''Requires''||
|''Source''||
!Usage
put {{{<div macro="editFields"></div>}}} into your EditTemplate.
or {{{<div macro="viewFields"></div>}}} into your ViewTemplate.
!Todo
Support newlines in input boxes.
!Code
***/
//{{{
(function($) {
var viewFields = config.macros.viewFields = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var fields = editFields.getFields(tiddler).concat(params);
var done = {};
for(var i = 0; i < fields.length; i++) {
var name = fields[i];
var val = tiddler.fields[name];
if(!done[name] && val) {
done[name] = true;
$("<div class='fieldValue' />").text("%0 : %1".format(name, val)).appendTo(place);
}
}
}
};
var editFields = config.macros.editFields = {
fieldType: {
images: ["image", "geo.marker"]
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var options = {
fields: params
};
this.createInterface(place, tiddler, options);
},
getFields: function(tiddler) {
var whitelisted = ["changecount"];
var fields = [];
for(var i in tiddler.fields) {
var val = tiddler.fields[i];
if(i.indexOf("server.") !== 0 && i.indexOf("_") !== 0 && typeof(val) == "string" && !whitelisted.contains(i) && val) {
fields.push(i);
}
}
return fields;
},
createInterface: function(place, tiddler, options) {
var fieldContainer = $("<div class='tiddlerCustomFields' />").appendTo(place);
var included = [];
if(tiddler) {
var fields = editFields.getFields(tiddler);
for(var i = 0; i < fields.length; i++) {
var name = fields[i];
var val = tiddler.fields[name];
this.addNewField(fieldContainer, name, val);
included.push(name);
}
}
for(var j = 0; j < options.fields.length; j++) {
var field = options.fields[j];
if(!included.contains(field)) {
this.addNewField(fieldContainer, field, "");
}
}
$("<button />").text("add new field").click(function() {
editFields.addNewField(fieldContainer, "", "");
}).appendTo(place);
},
addNewField: function(place, name, value) {
var container = $("<div />").appendTo(place);
if(editFields.fieldType.images.contains(name)) {
valueInput = $("<select />");
$("<option />").val("").text("").appendTo(valueInput);
$.each(store.filterTiddlers("[is[image]]"), function(i, tiddler) {
var opt = $("<option />").val(tiddler.title).text(tiddler.title).appendTo(valueInput)[0];
if(value === tiddler.title) {
$(opt).attr("selected", true);
}
});
} else {
type = value.indexOf("\n") > -1 ? "textarea" : "text";
var valueInput = type == "text" ? $("<input type='text' />") : $("<textarea />");
}
valueInput.attr("edit", name).val(value).appendTo(container);
$("<button class='delete' />").text("delete").click(function(ev) {
var answer = confirm("Are you sure you want to remove this field?");
if(answer) {
var attr = $(ev.target).attr("field");
var p = $(ev.target).parent();
$("[edit]", p).val("");
$(p).hide();
}
}).appendTo(container);
var nameInput = $("<input class='fieldName' type='text' />").val(name).
change(function(ev) {
var el = $(ev.target);
valueInput.attr("edit", el.val());
}).prependTo(container);
}
}
})(jQuery);
//}}}
/%
Filename: ExtendedBrainConfiguration.js
Usage: The following code is used as plugin within ExtendedBrain, a TiddlyWikiClassic based tool. It has to be tagged as systemConfig.
Version: 0.1
History: 0.1 / 2014-03-14 / Reto Stauss / Long time ago developped but now under version control
%/// // Zeitstempel im Titel von historischen Tiddlern
//{{{
config.options.extendedBrainTitleTimestamp = "YYYY-0MM-0DD 0hh:0mm /";
//}}}
// // Format des Zeitstempels zur Erzeugung einer eindeutigen Identifkation
//{{{
config.options.extendedBrainFormatUniqueId = "YYYY0MM0DD0hh0mm0ss";
//}}}
// // First day of a week is Sunday?
//{{{
config.options.extendedBrainFirstDayOfWeekSunday = false;
//}}}
// // Format of internal dates
//{{{
config.options.extendedBrainDateFormat = "YYYY-0MM-0DD";
config.options.extendedBrainDateWeekFormat = "YYYY-KW0WW";
config.options.extendedBrainDateMonthFormat = "YYYY-0MM";
//}}}
// // Format of displayed dates
//{{{
config.options.extendedBrainDisplayDateFormat = "DDD, DD. MMM YYYY";
config.options.extendedBrainDisplayDateWeekFormat = "YYYY-KW0WW";
config.options.extendedBrainDisplayDateMonthFormat = "YYYY-0MM";
//}}}
// // Strings
//{{{
config.options.extendedBrainDateField = "Feld";
config.options.extendedBrainDateIsUndefined = "ist undefiniert";
config.options.extendedBrainDateNoTiddlerFoundUniqueId = "Kein Tiddler gefunden mit der Unique ID =";
config.options.extendedBrainDateNoTiddlerFoundTitle = "Kein Tiddler gefunden mit dem Titel =";
config.options.extendedBrainDateEmpty = "";
//}}}
// // Status
//{{{
config.options.extendedBrainStatusOpenString = "Offen";
config.options.extendedBrainStatusOpenValue = 1;
config.options.extendedBrainStatusPausedString = "Wartend";
config.options.extendedBrainStatusPausedValue = 2;
config.options.extendedBrainStatusDoneString = "Erledigt";
config.options.extendedBrainStatusDoneValue = 3;
//}}}
/***
|''Name''|ExtendedBrainPlugin|
|''Description''|<...>|
|''Icon''|<...>|
|''Author''|Reto Stauss|
|''Contributors''|<...>|
|''Version''|<...>|
|''Date''|<...>|
|''Status''|@@experimental@@|
|''Source''|<...>|
|''CodeRepository''|<...>|
|''Copyright''|<...>|
|''License''|<...>|
|''CoreVersion''|<...>|
|''Requires''|<...>|
|''Overrides''|<...>|
|''Feedback''|<...>|
|''Documentation''|<...>|
|''Keywords''|<...>|
!Description
<...>
!Notes
<...>
!Usage of showWorkHeader
{{{
<<showWorkHeader tiddler:[TIDDLER_TITLE]>>
}}}
!!Parameters
[TIDDLER_TITLE]: title of the work tiddler
!!Examples
<<showWorkHeader tiddler:"ExtendedBrainPlugin">>
!Usage of showTitleOfField
{{{
<<showTitleOfField tiddler:[TIDDLER_TITLE] fieldname:[NAME_OF_FIELD]>>
}}}
!!Parameters
[NAME_OF_FIELD]: name of the field which contains a unique id of another tiddler
[TIDDLER_TITLE]: title of the tiddler which contains the field
!!Examples
<<showTitleOfField title:"ExtendedBrainPlugin" fieldname:"ref_to_origin_of_work">>
!Configuration Options
See [[ExtendedBrainConfiguration]].
!Unit tests
* [[Test checkUniqueId]]
* [[Test generateUniqueId]]
* [[Test addOffsetToDateOfPeriodToShow]]
* [[Test getDaysOfWeek]]
* [[Test getRefToOriginOfWork]]
!Revision History
!!v0.1 (2010-10-09)
* Initial Version
!To Do
*
!Code
***/
//{{{
if(!version.extensions.ExtendedBrainPlugin) { //# ensure that the plugin is only installed once
version.extensions.ExtendedBrainPlugin = { installed: true };
if(!config.extensions) { config.extensions = {}; } //# obsolete from v2.4.2
} //# end of "install only once"
config.macros.showWorkHeader= {};
config.macros.showWorkHeader.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
var parameters = paramString.parseParams(null, null, true);
var title = getParam(parameters, "tiddler");
var returnValue = "";
if(!store.tiddlerExists(title)) {
wikify(config.options.extendedBrainDateNoTiddlerFoundTitle + " " + title, place, null, tiddler);
} else {
returnValue = store.getTiddlerText("WorkHeader");
//alert(returnValue);
wikify(returnValue, place, null, tiddler);
//return returnValue;
}
};
config.macros.showTitleOfField= {};
config.macros.showTitleOfField.handler = function showTitleOfField(place, macroName, params, wikifier, paramString, tiddler) {
var parameters = paramString.parseParams(null, null, true);
var title = getParam(parameters, "tiddler");
var fieldname = getParam(parameters, "fieldname");
var returnValue = "";
if(!store.tiddlerExists(title)) {
wikify(config.options.extendedBrainDateNoTiddlerFoundTitle + " " + title, place);
} else {
if(store.getValue(title, fieldname) == undefined) {
// Check if field is defined
wikify(config.options.extendedBrainDateField + " {{{" + fieldname + "}}} " + config.options.extendedBrainDateIsUndefined, place, null, tiddler);
} else {
// Field is defined, find tiddler
var tids=store.reverseLookup("unique_id", store.getValue(title, fieldname),true);
for (var t=0; t<tids.length; t++) {
returnValue = returnValue + "[[" + tids[t].title + "]]";
}
if(returnValue != "") {
// Tiddler found
wikify(returnValue, place);
} else {
// No tiddler with the unique id in the passed field found
wikify(config.options.extendedBrainDateNoTiddlerFoundUniqueId + " " + store.getValue(title, fieldname), place, null, tiddler);
}
}
}
};
function generateUniqueId(uniqueId) {
/* Returns a unique number based on date and time */
/* If the passed value is 0 then the function generates a new unique id */
/* If the passed value is not 0 then the function checks if the value ist unique */
// var uniqueId = 0;
var notUnique= 0;
/* Generate the unique number */
if(uniqueId == 0) {
uniqueId = new Date().formatString(config.options.extendedBrainFormatUniqueId);
}
/* check if not already in use */
do {
if(checkUniqueId(uniqueId)) {
//alert(uniqueId + " is not unique");
uniqueId = parseInt(uniqueId) + 1;
notUnique = 1;
} else {
//alert(uniqueId + " is unique");
notUnique = 0;
}
} while(notUnique);
return uniqueId;
};
function checkUniqueId(candidate) {
/* Checks whether the passed number is unique */
var isInUse = 0;
var tids=store.getTiddlers("title");
/* Loop through all tiddlers */
for (var t=0; t<tids.length; t++) {
/* Check whether the candidate is in use */
if (store.getValue(tids[t].title,"unique_id") == candidate.toString()) {
/* Uhoh, is in use */
t = tids.length; // Leave the for loop and check again
isInUse = 1;
}
}
return isInUse;
};
function addOffsetToDateOfPeriodToShow(tiddler, offset) {
/* Adds the offset to the date in the field date_of_period_to_show of the passed tiddler */
var valid = new Boolean(false);
date = new Date(store.getValue(tiddler.title, "date_of_period_to_show"));
if(isNaN(offset)) {
/* Offset is not numeric */
if(offset == "+1w") {
/* Offset is +1 week */
valid = true;
date.setDate(date.getDate() + 7);
} else if(offset == "-1w") {
/* Offset is -1 week */
valid = true;
date.setDate(date.getDate() - 7);
} else if(offset == "+1m") {
/* Offset is +1 month days */
valid = true;
date.setMonth(date.getMonth() + 1);
} else if(offset == "-1m") {
/* Offset is -1 month days */
valid = true;
date.setMonth(date.getMonth() - 1);
} else {
/* Unknown offset */
valid = false;
}
} else {
/* Offset is numeric */
valid = true;
date.setDate(date.getDate() + offset);
}
if(valid) {
/* If the offset was valid set the field to the new date */
store.setValue(tiddler.title, "date_of_period_to_show", new Date(date).formatString("YYYY,0MM,0DD"));
}
};
function getDaysOfWeek(date) {
/* Returns a list of the days of the week the passed date is part of */
if(date == 0) {
// use current date
date = new Date();
} else {
// use passed date
}
var days = "(";
var day = 1; // Day of month
var dayOfWeek = 0;
// Offset for first day of the week
if(config.options.extendedBrainFirstDayOfWeekSunday) {
// First day of week set to Sunday
offset = 0;
dayOfWeek = date.getDay();
} else {
// First day of week set to Monday
offset = 1;
dayOfWeek = date.getDay() - 1;
if(dayOfWeek == -1) {
dayOfWeek = 6;
}
}
// First day of week of passed date
//day = date.getDate() - date.getDay() + offset; // getDate => returns day of month, getDay => returns day of week, + 1 because first day of getDay is sunday
day = date.getDate() - dayOfWeek; // getDate => returns day of month, getDay => returns day of week, + 1 because first day of getDay is sunday
date.setDate(day);
days = days + date.formatString(config.options.extendedBrainDateFormat);
//Following days
for(i=1;i<7;i++) {
date.setDate(day+i);
days = days + "|" + date.formatString(config.options.extendedBrainDateFormat);
}
days = days + ")";
return(days);
};
function getRefToOriginOfWork(tiddler2) {
/* Returns the unique id of the origin of work */
/* Lookup: */
/* 1. If the passed tiddler has a field 'ref_to_origin_of_work' and it is set => the value of the field is taken */
/* 2. If it has no field 'ref_to_origin_of_work' that it is itself an origin of work => the value of the field 'unique_id' is taken */
var returnValue = "";
var refToOriginOfWork = store.getValue(tiddler2.title, "ref_to_origin_of_work");
if( refToOriginOfWork == undefined || refToOriginOfWork == "") {
/* The passed tiddler is the origin of work */
returnValue = store.getValue(tiddler2.title, "unique_id");
} else {
/* The passed tiddler is not itself the origin of work */
returnValue = store.getValue(tiddler2.title, "ref_to_origin_of_work");
}
return returnValue;
};
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|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
<<<
2010.12.15 1.9.6 allow (but ignore) type="..." 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: 6, date: new Date(2010,12,15)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: type=\\\"[^\\\"]*\\\")?(?: src=\\\"([^\\\"]*)\\\")?(?: label=\\\"([^\\\"]*)\\\")?(?: title=\\\"([^\\\"]*)\\\")?(?: key=\\\"([^\\\"]*)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // external script library
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // inline code
if (show) // display source in tiddler
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create 'onclick' command link
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run script immediately
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name|InlineJavascriptPluginInfo|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|Documentation for InlineJavascriptPlugin|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Usage
<<<
This plugin adds wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be recognized as embedded javascript code. When a tiddler is rendered, the plugin automatically invokes any embedded scripts, which can be used to construct and return dynamically-generated output that is inserted into the tiddler content.
{{{
<script type="..." src="..." label="..." title="..." key="..." show>
/* javascript code goes here... */
</script>
}}}
All parameters are //optional//. When the ''show'' keyword is used, the plugin will also include the script source code in the output that it displays in the tiddler. This is helpful when creating examples for documentation purposes (such as used in this tiddler!)
__''Deferred execution from an 'onClick' link''__
<script label="click here" title="mouseover tooltip text" key="X" show>
/* javascript code goes here... */
alert('you clicked on the link!');
</script>
By including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered. You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text, and a {{{key="X"}}} parameter to specify an //access key// (which must be a //single// letter or numeric digit only).
__''Loading scripts from external source files''__
<script src="URL" show>
/* optional javascript code goes here... */
</script>You can also load javascript directly from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.
In addition to loading the javascript from the external file, you can also use this feature to invoke javascript code contained within the {{{<script>...</script>}}} markers. This code is invoked //after// the external script file has been processed, and can make immediate use of the functions and/or global variables defined by the external script file.
>Note: To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that is rendered as soon as your TiddlyWiki document is opened, such as MainMenu. For example: put your {{{<script src="..."></script>}}} syntax into a separate 'library' tiddler (e.g., LoadScripts), and then add {{{<<tiddler LoadScripts>>}}} to MainMenu so that the library is loaded before any other tiddlers that rely upon the functions it defines.
>
>Normally, loading external javascript in this way does not produce any direct output, and should not have any impact on the appearance of your MainMenu. However, if your LoadScripts tiddler contains notes or other visible content, you can suppress this output by using 'inline CSS' in the MainMenu, like this: {{{@@display:none;<<tiddler LoadScripts>>@@}}}
<<<
!!!!!Creating dynamic tiddler content and accessing the ~TiddlyWiki DOM
<<<
An important difference between TiddlyWiki inline scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document: in a typical web document, you use the {{{document.write()}}} (or {{{document.writeln()}}}) function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.
However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and instead will //completely replace the entire ~TiddlyWiki document in your browser window (which is clearly not a good thing!)//. In order to allow scripts to use {{{document.write()}}}, the plugin automatically converts and buffers all HTML output so it can be safely inserted into your tiddler content, immediately following the script.
''Note that {{{document.write()}}} can only be used to output "pure HTML" syntax. To produce //wiki-formatted// output, your script should instead return a text value containing the desired wiki-syntax content'', which will then be automatically rendered immediately following the script. If returning a text value is not sufficient for your needs, the plugin also provides an automatically-defined variable, 'place', that gives the script code ''direct access to the //containing DOM element//'' into which the tiddler output is being rendered. You can use this variable to ''perform direct DOM manipulations'' that can, for example:
* generate wiki-formatted output using {{{wikify("...content...",place)}}}
* vary the script's actions based upon the DOM element in which it is embedded
* access 'tiddler-relative' DOM information using {{{story.findContainingTiddler(place)}}}
Note:
''When using an 'onclick' script, the 'place' element actually refers to the onclick //link text// itself, instead of the containing DOM element.'' This permits you to directly reference or modify the link text to reflect any 'stateful' conditions that might set by the script. To refer to the containing DOM element from within an 'onclick' script, you can use "place.parentNode" instead.
<<<
!!!!!Instant "bookmarklets"
<<<
You can also use an 'onclick' link to define a "bookmarklet": a small piece of javascript that can be ''invoked directly from the browser without having to be defined within the current document.'' This allows you to create 'stand-alone' commands that can be applied to virtually ANY TiddlyWiki document... even remotely-hosted documents that have been written by others!! To create a bookmarklet, simply define an 'onclick' script and then grab the resulting link text and drag-and-drop it onto your browser's toolbar (or right-click and use the 'bookmark this link' command to add it to the browser's menu).
Notes:
*When writing scripts intended for use as bookmarklets, due to the ~URI-encoding required by the browser, ''you cannot not use ANY double-quotes (") within the bookmarklet script code.''
*All comments embedded in the bookmarklet script must ''use the fully-delimited {{{/* ... */}}} comment syntax,'' rather than the shorter {{{//}}} comment syntax.
*Most importantly, because bookmarklets are invoked directly from the browser interface and are not embedded within the TiddlyWiki document, there is NO containing 'place' DOM element surrounding the script. As a result, ''you cannot use a bookmarklet to generate dynamic output in your document,'' and using {{{document.write()}}} or returning wiki-syntax text or making reference to the 'place' DOM element will halt the script and report a "Reference Error" when that bookmarklet is invoked.
Please see [[InstantBookmarklets]] for many examples of 'onclick' scripts that can also be used as bookmarklets.
<<<
!!!!!Special reserved function name
<<<
The plugin 'wraps' all inline javascript code inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.
<<<
!!!!!$(...) 'shorthand' function
<<<
As described by Dustin Diaz [[here|http://www.dustindiaz.com/top-ten-javascript/]], the plugin defines a 'shorthand' function that allows you to write:
{{{
$(id)
}}}
in place of the normal standard javascript syntax:
{{{
document.getElementById(id)
}}}
This function is provided merely as a convenience for javascript coders that may be familiar with this abbreviation, in order to allow them to save a few bytes when writing their own inline script code.
<<<
!!!!!Examples
<<<
simple dynamic output:
><script show>
document.write("The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
if (!window.story) window.story=window;
var title=story.findContainingTiddler(place).getAttribute("tiddler");
var size=store.getTiddlerText(title).length;
return title+" is using "+size+" bytes";
</script>
dynamic output from an 'onclick' script, using {{{document.write()}}} and/or {{{return "..."}}}
><script label="click here" show>
document.write("<br>The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
creating an 'onclick' button/link that accesses the link text AND the containing tiddler:
><script label="click here" title="clicking this link will show an 'alert' box" key="H" show>
if (!window.story) window.story=window;
var txt=place.firstChild.data;
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
alert('Hello World!\nlinktext='+txt+'\ntiddler='+tid);
</script>
dynamically setting onclick link text based on stateful information:
>{{block{
{{{
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.previousSibling.innerHTML=on?"disable":"enable";
</script>
}}}
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.innerHTML=on?"enable":"disable";
</script>
}}}
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function inlineJavascriptDemo() { alert('Hello from demo.js!!') } }}}
>>{{{displayMessage('InlineJavascriptPlugin: demo.js has been loaded');}}}
>note: When using this example on your local system, you will need to download the external script file from the above URL and install it into the same directory as your document.
>
><script src="demo.js" show>
return "inlineJavascriptDemo() function has been defined"
</script>
><script label="click to invoke inlineJavascriptDemo()" key="D" show>
inlineJavascriptDemo();
</script>
<<<
!!!!!Revisions
<<<
2010.12.15 1.9.6 allow (but ignore) type="..." syntax
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
2008.06.11 1.9.3 added $(...) function as 'shorthand' for document.getElementById()
2008.03.03 1.9.2 corrected fallback declaration of wikifyPlainText() (fixes Safari "parse error")
2008.02.23 1.9.1 in onclick function, use string instead of array for 'bufferedHTML' (fixes IE errors)
2008.02.21 1.9.0 output from 'onclick' scripts (return value or document.write() calls) are now buffered and rendered into into a span following the script. Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed). Thanks to Xavier Verges for suggestion and preliminary code.
2008.02.14 1.8.1 added backward-compatibility for use of wikifyPlainText() in TW2.1.3 and earlier
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 1.8.0 added support for key="X" syntax to specify custom access key definitions
2007.12.15 1.7.0 autogenerate URI encoded HREF on links for onclick scripts. Drag links to browser toolbar to create bookmarklets. IMPORTANT NOTE: place is NOT defined when scripts are used as bookmarklets. In addition, double-quotes will cause syntax errors. Thanks to PaulReiber for debugging and brainstorming.
2007.11.26 1.6.2 when converting "document.write()" function calls in inline code, allow whitespace between "write" and "(" so that "document.write ( foobar )" is properly converted.
2007.11.16 1.6.1 when rendering "onclick scripts", pass label text through wikifyPlainText() to parse any embedded wiki-syntax to enable use of HTML entities or even TW macros to generate dynamic label text.
2007.02.19 1.6.0 added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
2006.10.16 1.5.2 add newline before closing '}' in 'function out_' wrapper. Fixes error caused when last line of script is a comment.
2006.06.01 1.5.1 when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly
2006.04.19 1.5.0 added 'show' parameter to force display of javascript source code in tiddler output
2006.01.05 1.4.0 added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.
2005.12.13 1.3.1 when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by UdoBorkowski
2005.11.09 1.3.0 for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by BradleyMeck
2005.11.08 1.2.0 handle loading of javascript from an external URL via src="..." syntax
2005.11.08 1.1.0 pass 'place' param into scripts to provide direct DOM access
2005.11.08 1.0.0 initial release
<<<
/***
|''Name:''|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);
}
//}}}
[[WelcomeToTiddlyspot]] [[GettingStarted]]
-----
ExtendedBrainPlugin
[[Configuration|ExtendedBrainConfiguration]]
[[Testcase]]
/***
|''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"
});
*/
//}}}
!Test 1
Using inline javascript:
<script>
return store.getTiddlerText("WorkHeader");
</script>
!Test 2
Using showWorkHeader macro from ExtendedBrainPlugin:
<<showWorkHeader tiddler:{{tiddler.title}}>>
<<toolbar fields>>
/***
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 = 'extendedbrain';
// 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,{
'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"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].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"),
'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")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 29/11/2012 21:28:12 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . |
| 29/11/2012 21:29:10 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . | ok |
| 29/11/2012 21:40:52 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . |
| 29/11/2012 21:44:01 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . |
| 30/11/2012 09:50:33 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . | failed |
| 30/11/2012 09:51:15 | RetoStauss | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . |
| 01/07/2013 15:23:24 | YourName | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.php|http://extendedbrain.tiddlyspot.com/store.php]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | |
| 01/07/2013 15:26:48 | YourName | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . |
| 14/03/2014 23:24:50 | extendedbrain | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.tiddlyspot.com/index.html]] | . | ok |
| 14/03/2014 23:25:35 | extendedbrain | [[/|http://extendedbrain.tiddlyspot.com/]] | [[store.cgi|http://extendedbrain.tiddlyspot.com/store.cgi]] | . | [[index.html | http://extendedbrain.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");
//}}}
| !Tätigkeitsursprung|<<showTitleOfField tiddler:{{tiddler.title}} fieldname:"ref_to_origin_of_work">>|
| !Tätigkeitsart|<<edit kind_of_work@>>|
| !Tätigkeitsort|<<edit location_of_work@>>|
| !Geschätzter Aufwand [h]|<<edit estimated_time_effort@>>|
| !Bisheriger Aufwand [h]||
| !Status|<<tiddler CheckboxToggleTag with: Erledigt Offen>> Erledigt|