/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser
Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)
<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations
----
Also see AdvancedOptions
<<importTiddlers>>
/*{{{*/
window.saveChanges = function(){};
setStylesheet(
"label {width:8em; float:left; text-align:right; width:9em; font-size:1.1em; padding:3px; height:1.5em: top:-20px; margin: 0px -2px 0 0;}"+
// "div.wizardFooter {padding-left:0em}"+
"div.wizardStep > input {display:fixed; padding:3px; margin-bottom:5px; margin-top:0px; margin-right:0px}",
'labelStyles');
merge(config.macros.importTiddlers, {
wizardTitle: "Import tiddlers",
step1Title: "Step 1: Locate the server or TiddlyWiki file",
step1Html: "Specify the type of the server: <select name='selTypes'><option value=''>Choose...</option></select><br>Enter the URL here: <input type='text' size=50 name='txtPath'><br><input type='hidden' size=50 name='txtBrowse'><br><hr>...or select a pre-defined feed: <select name='selFeeds'><option value=''>Choose...</option></select>"
});
merge(config.optionsDesc,{
txtUserName: "",
chkRegExpSearch: "Enable regular expressions for searches",
chkCaseSensitiveSearch: "Case-sensitive searching",
chkIncrementalSearch: "Incremental key-by-key searching",
chkAnimate: "Enable animations",
chkSaveBackups: "",
chkAutoSave: "",
txtTheme: "Change the TiddlyWiki theme being used",
chkGenerateAnRssFeed: "",
chkSaveEmptyTemplate: "",
chkOpenInNewWindow: "Open external links in a new window",
chkToggleLinks: "Clicking on links to open tiddlers causes them to close",
chkHttpReadOnly: "",
chkForceMinorUpdate: "",
chkConfirmDelete: "Require confirmation before deleting tiddlers",
chkInsertTabs: "Use the tab key to insert tab characters instead of moving between fields",
txtBackupFolder: "",
txtMaxEditRows: "Maximum number of rows in edit boxes",
txtFileSystemCharSet: "Default character set for saving changes (Firefox/Mozilla only)"});
merge(config.macros.options,{
wizardTitle: "Change Settings",
step1Title: "",
step1Html: ' These options are saved in a cookie.'
});
merge(config.macros.options,{
wizardTitle:"Advanced settings",
step1Title:null,
unknownDescription: "//(unknown)//",
listViewTemplate: {
columns: [
{name: 'Option', field: 'option', title: "", type: 'String'},
{name: 'Description', field: 'description', title: "", type: 'WikiText'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]
}
});
window.ccTiddlyVersion = '1.7.5';
window.workspacePermission= {};
window.url = "http://wiki.osmosoft.com/alpha";
window.url= 'http://wiki.osmosoft.com/alpha/';
window.workspace = "pardelib";
window.fullUrl = window.url+"?workspace="+window.workspace;
if (config.options.txtTheme == "")
config.options.txtTheme = 'purpleTheme';
workspacePermission.upload = 1;workspacePermission.anonC = 0 ;
workspacePermission.anonR = 1;
workspacePermission.anonU = 0;
workspacePermission.anonD = 0;
workspacePermission.userC = 1 ;
workspacePermission.userR = 1;
workspacePermission.userU = 1;
workspacePermission.userD = 1;
workspacePermission.canCreateWorkspace = 1;
// hide new journal
config.macros.newJournal.handler=function(place,macroName,params,wikifier,paramString,tiddler){};
// hide new tiddler
config.macros.newTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler){};
window.workspace_delete = "D";
window.workspace_udate = "D";
var serverside={
url:"http://wiki.osmosoft.com/alpha", //server url, for use in local TW or TW hosted elsewhere
workspace:"pardelib",
queryString:"workspace=pardelib",
debug:0, //debug mode, display alert box for each action
passwordTime:0, //defines how long password variable store in cookie. 0 = indefinite
messageDuration:5000, //displayMessage autoclose duration (in milliseconds), 0=leave open
loggedIn:0,
can_create_account:"1",
openId:"1"
};
config.defaultCustomFields = {"server.host":window.url, "server.type":"cctiddly", "server.workspace":window.workspace};
config.shadowTiddlers.OptionsPanel = "[[help|Help]] <br />[[settings|AdvancedOptions]]<br /><<ccOptions>>";
readOnly =false;
config.options.chkHttpReadOnly = false; //make it HTTP writable by default
config.options.chkSaveBackups = false; //disable save backup
//config.options.chkAutoSave = false; //disable autosave
config.options.chkUsePreForStorage = false;
/*}}}*/
(this content is a work in progress)
!!!ccTiddly Tiddlers
[[AnonDefaultTiddlers]]
Allows you to specify a different set of tiddlers to be loaded for anonymous users. Logged in users will be shown the [[DefaultTiddlers]].
[[ccAssignments]]
!!! Predefined ccTiddly Tags
!!!!wizard
Displays the tiddler without showing the date editor tags or title.
!!!!private
Only administrators of a workspace can read tiddlers tagged private.
!!! Working Offline :
To take a copy of a ccTiddly workspace offline add &standalone=1 to the end of the URI and you will be prompted to download an offline file.
!!!{{{<<ccUpload>>}}}
If enabled on the server users can upload files to the ccTiddly server
!!!{{{<<ccLogin>>}}}
Displays the login box if the users is not logged in, if the user is logged in they are shown a logout button
!!!{{{<<ccLoginStatus>>}}}
As with {{{<<ccLogin>>}}} except this displays a link to the login tiddler so can be used where space is tight.
!!!{{{<<ccCreateWorkspace>>}}}
Allows users with permission to create a workspace and define its permissions.
!!!{{{<<ccEditWorkspace>>}}}
Allows admin users to change the permission of a workspace.
!!!{{{<<ccAdmin>>}}}
Allows admin users to add and remove admin users for a workspace.
!!!{{{<<ccVersion>>}}}
Allows users to confirm which version of ccTiddly they are using.
~TiddlyWiki is a single html file containing all the characteristics of a wiki - all the content, all the functionality (including editing, saving, tagging and searching) and the style sheet. Because it's a single file, it's very portable - you can email it, put it on a web server or share it via a USB stick. ccTiddly provides a serverside backend to ~TiddlyWiki so you can store your content on the web and access it from anywhere.
Together the two provide a powerful combination which allows you to collaborate with your colleages online, you can then tear a copy of all the work to take on a plane or train journey. When you have found an internet connection again you can sync your changes with the online copy and you will be notified of any conflicts.
Some things you could do with ccTiddly workspace include:
* A team/public Website
* A Blog
* A personal notebook
* A GTD ("Getting Things Done") productivity tool
* A collaboration/communication tool
* A TeamTasks implementation
* For building websites (this site is a TiddlyWiki file!)
* For rapid prototyping
* ...and much more!
You can import and export data to and from all sorts of places. Check out the backstage > import options. There's a more detailed list of features here.
<<slider cctHelpIntro [[ccTiddly Introduction]] "ccTiddly Introduction »" "A introduction to the basics of TiddlyWiki.">>
<<slider cctHelpFormatting [[TiddlyWiki Formatting Guide]] "Tiddly Wiki Formatting Guide »" "A basic guide to TiddlyWiki formatting.">>
<<slider cctHelpccTiddlyMacros [[ccTiddly Macros]] "ccTiddly Macros »" "A Guide to all the ccTiddly Macros">>
<<slider cctHelpTiddlyWikiMacros [[TiddlyWiki Macros]] "TiddlyWiki Macros »" "A Guide to all the TiddlyWiki Macros">>
<<ccAdmin>>
More info on Osmosoft can be found at [[osmosoft.com|http://osmosoft.com/]]
Please see the TiddlyWiki community wiki documentation : http://tiddlywiki.org/wiki/TiddlyWiki_Markup
!!!{{{<<today>>}}}
Shows current date.
!!!{{{<<version>>}}}
This macro shows the version number of the current TiddlyWiki document.
!!!{{{<<Alltags>>}}}
Lists all tags. Clicking on a tag lists all the tiddlers assigned that tag.
!!!{{{<<List [type]>>}}}
Parameters : (all (default), missing, orphans, shadowed, touched, filter)
!!!{{{<<Timeline [date] [length] [format]>>}}}
The timeline macro creates a list of tiddlers sorted by a date specified.
Example :
{{{<<timeline "modified" "0" "ddd, YYYY-0MM-0DD">>}}}
Produces :
<<timeline "modified" "0" "ddd, YYYY-0MM-0DD">>
!!!{{{<<Slider cookie tiddler label tooltip>>}}}
The slider macro allows embedding tiddlers within another tiddler, with the option to toggle the visibility of the transcluded contents.
* cookie: variable to save the state of the slider
* tiddler: name of the tiddler to include in the slider
* label: title text of the slider
* tooltip: tooltip text of the slider
Example
{{{<<slider chkTestSlider [[OptionsPanel]] "Options" "Open advanced options">>}}}
Produces :
<<slider chkTestSlider [[OptionsPanel]] "Options" "Open advanced options">>
!!!{{{<<Tabs>>}}}
The tabs macro creates an area where it displays one of several tiddlers alternately, as the user clicks on the tab labels at the top.
It is used like this:
{{{<<tabs ID Label1 Tip1 Tiddler1 Label2 Tip2 Tiddler2 [Label3 ...]>>}}}
produces :
<<tabs ID Label1 Tip1 Tiddler1 Label2 Tip2 Tiddler2 [Label3 ...]>>
* ID: specifies the name of a cookie used to save the information about which tab was displayed last.
* Label1, Label2, ... define the labels that are displayed at the top of the area for each tab
* Tip1, Tip2, ... define tooltips that explain, somewhat more verbosely than the labels, what you can expect to find on each tab.
* Tiddler1, Tiddler2, ... name the tiddlers that are displayed on each tab.
Obviously, there must be exactly three strings for each tab.
The syntax for the tabs macro looks like this:
{{{<<tabs txt[cookieName]
"[label]" "[title]" [[tiddler]]
"[label]" "[title]" [[tiddler]]
...
>>}}}
produces :
<<tabs txt[cookieName]
"[label]" "[title]" [[tiddler]]
"[label]" "[title]" [[tiddler]]
...
>>
!!!{{{<<Tagging [tag]>>}}}
This macro generates a list of tiddlers that carry the specified tag.
<<tagging [tag]>>
If the tag parameter is not specified, the current tiddler's name will be used instead.
!!!{{{<<Tagchooser>>}}}
!!!{{{<<NewJournal>>}}}
This macro generates a button to create a journal tiddler, using the current time and date as title.
It is otherwise identical to the NewTiddler macro.
Example :
{{{<<newJournal [date format]>>}}}
Produces :
<<newJournal [date format]>>
The optional parameter can be used to specify a custom date format.
In addition, all of the NewTiddler macro's parameters are valid.
!!!{{{<<NewTiddler>>}}}
Usage
<<newTiddler [parameters]>>
Parameters
This macro uses named parameters. All parameters are optional.
|Parameter|Description|
|label |button label|
|prompt|button tooltip|
|title|title for the new tiddler (defaults to "New Tiddler")|
|text|contents for the new tiddler|
|tag|tag to be applied to the new tiddler (parameter can be used repeatedly to specify multiple tags)|
|accessKey|single letter to use as access key to trigger the button|
|focus|which of the editable fields to default the focus to (e.g. "title", "text", "tags")|
|template|template tiddler to use to display the new tiddler (defaults to EditTemplate)|
|fields|custom fields to be assigned to the new tiddler, in name:value;name:value; format|
Only fields contained as input fields in the specified template can be primed with an initial value.
[edit] Example
<<newTiddler
label:"New Tiddler"
text:"Hello world."
tag:"test"
tag:"an example"
accessKey:"1"
focus:"tags"
>>
!!!{{{<<Savechanges>>}}}
!!!{{{<<Search>>}}}
This macro creates an input field to perform full-text searches on a TiddlyWiki document's tiddler contents.
[edit] Usage
Example :
{{{<<search [value]>>}}}
Produces :
<<search [value]>>
By specifiying the value parameter, the search form can be "preloaded" with the desired term.
[edit] Options
This section is still incomplete. You can help by contributing to its expansion.
Please improve the article, or discuss the issue on the talk page.
* case-sensitive
* regular expressions
!!!{{{<<Gradient>>}}}
The Gradient macro allows simple horizontal and vertical coloured gradients. They are constructed from coloured HTML elements, and don't require any images to work.
The Gradient macro is an extended macro that processes the text after it up until the next '
>>
' sequence. It looks like this:
Example :
{{{<<gradient vert #ffffff #ffdddd #ff8888>>gradient fill>>}}}
Produces :
<<gradient vert #ffffff #ffdddd #ff8888>>gradient fill>>
The first parameter can be vert or horiz to indicate the direction of the gradient. The following parameters are two or more colours (CSS RGB(r,g,b) format is also acceptable). The macro constructs a smooth linear gradient between each of the colours in turn.
Inline CSS definitions can be added to gradient fills like this:
Example :
{{{<<gradient vert #000000 #660000 #aa2222>>color:#ffffff;font-size:12pt;Darkness>>}}}
Produces :
<<gradient vert #000000 #660000 #aa2222>>color:#ffffff;font-size:12pt;Darkness>>
!!!{{{<<Closeall>>}}}
!!!{{{<<Permaview>>}}}
Changes the browser address bar to a permalink to the current Tiddler or the set of open tiddlers. It is used with the ToolbarMacro like this:
Example :
{{{<<toolbar permalink>>}}}
Produces :
<<toolbar permalink>>
!!!{{{<<Toolbar>>}}}
The ToolbarMacro is used in the TemplateMechanism to define the toolbar that appearthat appear either in EditMode or in ViewMode. The arguments to the ToolbarMacro is a list of command names, as discussed in the CommandMechanism..
You can precede a command name with a "+" to specify a default command that is automatically chosen when a tiddler is double-clicked, or the ctrl-Enter key combination pressed. Similarly, precede it with "-" to specify a command to be chosen when the Escape key is pressed.
!!!{{{<<Annotations>>}}}
!!!{{{<<Edit>>}}}
The command <<edit>> switches from ViewMode to EditMode. The EditMacro is either a double mouse click inside the tiddler or the entry 'edit' in the tiddler's Toolbar. It is used in ViewTemplate as ToolbarMacro like this:
Example :
{{{<<toolbar +editTiddler>>}}}
Produces :
<<toolbar +editTiddler>>
!!!{{{<<Message>>}}}
!!!{{{<<Refreshdisplay>>}}}
!!!{{{<<View fieldname how...>>}}}
Retrieves a specified field (given by fieldname) from the tiddler to be displayed and outputs its value in one of the following ways (the optional //how// parameter):
* (unspecified): render as is (without formatting)
* link: format as a link (using createTiddlyLink)
* wikified: format using all the normal rendering rules
* date: expects a value of the form YYYYMMDDHHMM and outputs it using either a specified format (...) or config.views.wikified.dateFormat
The standard field names are:
* title - the tiddler title
* tiddler - the tiddler title (as well)
* text - the text of the tiddler
* modifier - the person who last modified it
* modified - date&time of last modification
* created - when it was created
* tags - the tiddler tags
If your tiddlers contain custom fields, they could be specified as well.
The view macro is used extensively in the standard tiddler rendering templates (ViewTemplate and EditTemplate).
config.macros.ccAbout={};
merge(config.macros.ccAbout,{
buttonBackstageText:"about",
buttonBackstageTooltip:"Find out more about ccTiddly ",
stepAboutTitle:"About",
stepAboutTextStart:"You are running ccTiddly ",
stepAboutTextEnd:"More info about ccTiddly can be found at <a target=new href=http://www.tiddlywiki.org/wiki/CcTiddly>http://www.tiddlywiki.org/wiki/CcTiddly</a><br/><br/> More information about TiddlyWiki can be found at <a target=new href=http://www.tiddlywiki.com>http://www.tiddlywiki.com</a><br/>"
});
config.macros.ccChangePassword={};
merge(config.macros.ccChangePassword,{
title:"Change Password",
subTitle : "for user ",
step1Html: " <label for='old'>Old Password </label><input name='old' type='password'/><br/> <label for='new1'>New Password </label> <input name='new1' type='password' /><br /><label for='new2'>Repeat Password</label> <input name='new2' type='password' /> ",
buttonChangeText:"Change Password",
buttonChangeToolTip:"Click to change your password",
buttonCancelText:"Cancel",
buttonCancelToolTip:"Click to cancel",
noticePasswordsNoMatch : "Your new passwords do not match",
noticePasswordWrong : "Your password is incorrect.",
noticePasswordUpdated : "Your Password has been updated",
noticePasswordUpdateFailed : "Your Password was NOT updated."
});
config.macros.ccAdmin = {}
merge(config.macros.ccAdmin,{
stepAddTitle:"Add a new Workspace Administrator",
WizardTitleText:"Workspace Administration.",
buttonDeleteText:"Delete Users",
buttonDeleteTooltip:"Click to delete users.",
buttonAddText:"Add User",
buttonAddTooltip:"Click to add user.",
buttonCancelText:"Cancel",
buttonCalcelTooltip:"Calcel adding user.",
buttonCreateText:"Make User Admin",
buttonCreateTooltip:"Click to make user admin.",
labelWorkspace:"Workspace: ",
labelUsername:"Username : ",
stepErrorTitle:"You need to be an administrator of this workspace.",
stepErrorText:"Permission Denied to edit workspace : ",
stepNoAdminTitle:"There are no admins of this workspace.",
stepManageWorkspaceTitle:"",
listAdminTemplate: {
columns: [
{name: 'Selected', field: 'Selected', rowName: 'name', type: 'Selector'},
{name: 'Name', field: 'name', title: "Username", type: 'String'},
{name: 'Last Visit', field: 'lastVisit', title: "Last Login", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
function ccTiddlyAutoSave(){return this;}
merge(ccTiddlyAutoSave,{
msgSaved:"Saved ",
msgError:"There was an error saving "
});
config.macros.ccCreateWorkspace = {}
merge(config.macros.ccCreateWorkspace, {
wizardTitle:"Create Workspace",
buttonCreateText:"create",
buttonCreateWorkspaceText:"Create Workspace",
buttonCreateTooltip:'Create new workspace',
errorPermissions:"You do not have permissions to create a workspace. You may need to log in.",
msgPleaseWait:"Please wait, your workspace is being created.",
msgWorkspaceAvailable:"Workspace name is available.",
errorWorkspaceNameInUse:"Workspace name is already in use.",
stepTitle:"Please enter workspace name",
stepCreateHtml:"<input class='input' id='workspace_name' name='workspace_name' value='"+workspace+"' tabindex='1' /><span></span><input type='hidden' name='workspace_error'></input><h2></h2><input type='hidden' name='workspace_url'></input>"
});
config.macros.ccEditWorkspace={};
merge(config.macros.ccEditWorkspace,{
WizardTitleText:"Edit Workspace Permissions",
stepEditTitle:null,
stepLabelCreate:'Create',
stepLabelRead:'Read',
stepLabelUpdate:'Edit',
stepLabelDelete:'Delete',
stepLabelPermission:'',
stepLabelAnon:' Anonymous ',
stepLabelUser:' Authenticated ',
stepLabelAdmin:' Admin ',
buttonSubmitCaption:"Update Workspace Permissions",
buttonSubmitToolTip:"Update workspace permissions",
button1SubmitCaption:"ok",
button1SubmitToolTip:"review permissions",
step2Error:"Error",
errorTextPermissionDenied:"You do not have permissions to edit this workspace permissions. You may need to log in.",
errorUpdateFailed:"Permissions Not changed"
});
config.macros.ccFile = {};
merge(config.macros.ccFile,{
wizardTitleText:"Manage Files",
wizardStepText:"Manage files in workspace ",
buttonDeleteText:"Delete Files",
buttonDeleteTooltip:"Click to Delete files.",
buttonUploadText:"Upload File",
buttonUploadTooltip:"Click to Upload files.",
buttonCancelText:"Cancel",
buttonCancelTooltip:"Click to cancel.",
labelFiles:"Existing Files ",
errorPermissionDeniedTitle:"Permission Denied",
errorPermissionDeniedUpload:"You do not have permissions to create a file on this server. ",
errorPermissionDeniedView:"You do not have permissions to view files in this workspace. ",
listAdminTemplate: {
columns: [
{name: 'wiki text', field: 'wikiText', title: "", type: 'WikiText'},
{name: 'Selected', field: 'Selected', rowName: 'name', type: 'Selector'},
{name: 'Name', field: 'name', title: "File", type: 'WikiText'},
{name: 'Size', field: 'fileSize', title: "size", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
config.macros.ccLogin={sha1:true};
merge(config.macros.ccLogin,{
WizardTitleText:null,
usernameRequest:"Username",
passwordRequest:"Password",
stepLoginTitle:null,
stepLoginIntroTextHtml:"<label>username</label><input name=username id=username tabindex='1'><br /><label>password</label><input type='password' tabindex='2' class='txtPassword'><input name='password'>",
stepDoLoginTitle:"Logging you in",
stepDoLoginIntroText:"we are currently trying to log you in.... ",
stepForgotPasswordTitle:"Password Request",
stepForgotPasswordIntroText:"Please contact your system administrator or register for a new account. <br /><input id='forgottenPassword' type='hidden' name='forgottenPassword'/>",
stepLogoutTitle:"Logout",
stepLogoutText:"You are currently logged in as ",
buttonLogout:"logout",
buttonLogoutToolTip:"Click here to logout.",
buttonLogin:"Login",
buttonlogin:"login",
buttonLoginToolTip:"Click to Login.",
buttonCancel:"Cancel",
buttonCancelToolTip:"Cancel transaction ",
buttonForgottenPassword:"Forgotten Password",
buttonSendForgottenPassword:"Mail me a New Password",
buttonSendForgottenPasswordToolTip:"Click here if you have forgotten your password",
buttonForgottenPasswordToolTip:"Click to be reminded of your password",
msgNoUsername:"Please enter a username",
msgNoPassword:"Please enter a password",
msgLoginFailed:"Login Failed, please try again. ",
configURL:url+"/handle/login.php",
configUsernameInputName:"cctuser",
configPasswordInputName:"cctpass",
configPasswordCookieName:"cctPass"
});
config.macros.ccLoginStatus={};
merge(config.macros.ccLoginStatus,{
textDefaultWorkspaceLoggedIn:"Viewing default workspace",
textViewingWorkspace:"Viewing Workspace : ",
textLoggedInAs:"Logged in as ",
textNotLoggedIn:"You are not logged in.",
textAdmin:"You are an Administrator."
});
config.macros.ccOptions={};
merge(config.macros.ccOptions, {
linkManageUsers:"users",
linkPermissions:"permissions",
linkFiles:"files",
linkPassword:"password",
linkCreate:"create",
linkOffline:"offline",
linkStats:"statistics"
});
config.macros.register={};
merge(config.macros.register,{
usernameRequest:"username",
passwordRequest:"password",
passwordConfirmationRequest:"confirm password",
emailRequest:"email",
stepRegisterTitle:"Register for an account.",
stepRegisterIntroText:"Hi, please register below.... ",
stepRegisterHtml:"<label> username</label><input class='input' id='reg_username' name='reg_username' tabindex='1'/><span></span><input type='hidden' name='username_error'></input><br /><label>email</label><input class='input' name=reg_mail id='reg_mail' tabindex='2'/><span> </span><input type='hidden' name='mail_error'></input><br/><label>password</label><input type='password' class='input' id='password1' name='reg_password1' tabindex='3'/><span> </span><input type='hidden' name='pass1_error'></input><br/><label>confirm password</label><input type='password' class='input' id='password2' name='reg_password2' tabindex='4'/><span> </span><input type='hidden' name='pass2_error'></input>",
buttonCancel:"Cancel",
buttonCancelToolTip:"Cancel transaction ",
buttonRegister:"Register",
buttonRegisterToolTip:"click to register",
msgCreatingAccount:"Attempting to create the account for you.",
msgNoUsername:"No username entered",
msgEmailOk:"Email address is OK.",
msgNoPassword:"no password entered.",
msgDifferentPasswords:"Your Passwords do not match.",
msgUsernameTaken:"The username requested has been taken.",
msgUsernameAvailable:"The username is available.",
step2Title:"",
step2Html:"Please wait while we create you an account...",
errorRegisterTitle:"Error",
errorRegister:"User not created, please try again with a different username."
});
config.macros.ccStats={};
merge(config.macros.ccStats,{
graph24HourTitle:"Last 24 hours",
graph24HourDesc:"The number of views of this workspace in the past 24 hours",
graph20MinsTitle:"Last 20 Minutes",
graph20MinsDesc:"The number of views of this workspace in the last 20 minutes",
graph7DaysTitle:"Last 7 days",
graph7DaysDesc:"The number of views of this workspace in the last 7 days.",
graph5MonthsTitle:"Last 5 months",
graph5MonthsDesc:"The number of views of this workspace in the past 30 days.",
errorPermissionDenied:"Permissions Denied to data for %0 You need to be an administrator on the %1 workspace.",
stepTitle:"Workspace Statistics"
});
/***
|''Name:''|ccLoadRemoteFileThroughProxy (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:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''~CoreVersion:''|2.2.0|
|''Date:''|Nov 6, 2008|
|''Version:''|0.1|
***/
//{{{
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){
var urlStart = window.url;
if((document.location.toString().substr(0,4)=="http")&&(url.substr(0,4)=="http")){
url=urlStart+"/"+store.getTiddlerText("SiteProxy","/proxy")+url;
displayMessage(url);
}
var a = bidix.core.loadRemoteFile(url,callback,params);
return a;
}
//}}}
// ccAdaptorCommandsPlugin //
function ccTiddlyAdaptor(){}
merge(ccTiddlyAdaptor,{
errorTitleNotSaved:"<h1>Your changes were NOT saved.</h1>",
errorTextSessionExpired:"Your Session has expired. <br /> You will need to log into the new window and then copy your changes from this window into the new window. ",
errorTextConfig:"There was a conflict when saving. <br /> Please open the page in a new window to see the changes.",
errorTextUnknown:"An unknown error occured.",
errorClose:"close",
buttonOpenNewWindow:"Open a Window where I can save my changes .... ",
buttonHideThisMessage:"Hide this message",
msgErrorCode:"Error Code : "
});
//{{{
config.commands.revisions = {};
merge(config.commands.revisions,{
text: "revisions",
tooltip: "View another revision of this tiddler",
loading: "loading...",
done: "Revision downloaded",
revisionTooltip: "View this revision",
popupNone: "No revisions",
revisionTemplate: "%0 r:%1 m:%2",
dateFormat:"YYYY mmm 0DD 0hh:0mm"
});
config.commands.deleteTiddlerHosted = {};
merge(config.commands.deleteTiddlerHosted,{
text: "delete",
tooltip: "Delete this tiddler",
warning: "Are you sure you want to delete '%0'?",
hideReadOnly: true,
done: "Deleted "
});
// Ensure that the plugin is only installed once.
if(!version.extensions.AdaptorCommandsPlugin) {
version.extensions.AdaptorCommandsPlugin = {installed:true};
config.commands.saveTiddlerHosted1 = {};
merge(config.commands.saveTiddlerHosted1, config.commands.saveTiddler);
config.commands.saveTiddlerHosted1.handler = function(event,src,title)
{
var tiddlerElem = story.getTiddler(title);
var fields = {};
story.gatherSaveFields(tiddlerElem,fields);
var newTitle = fields.title || title;
if(!store.tiddlerExists(newTitle))
newTitle = newTitle.trim();
if(newTitle==title){ // we are not renaming the tiddler
var newTitle = story.saveTiddler(title,event.shiftKey);
if(newTitle)
story.displayTiddler(null,newTitle);
} else { // the tiddler is being renamed
var tiddler = store.fetchTiddler(title);
if(store.tiddlerExists(newTitle) && newTitle != title) {
if(!confirm(config.messages.overwriteWarning.format([newTitle.toString()])))
return false;
}
var adaptor = new ccTiddlyAdaptor();
var userParams = {minorUpdate:event.shiftKey};
var context = {title:title, newTitle:newTitle, workspace:window.workspace};
adaptor.rename(context, userParams, config.commands.saveTiddlerHosted1.callback);
}
return false;
};
// implementing closeTiddler without the clearMessage();
Story.prototype.closeTiddler = function(title,animate,unused)
{
var tiddlerElem = this.getTiddler(title);
if(tiddlerElem) {
this.scrubTiddler(tiddlerElem);
if(config.options.chkAnimate && animate && anim && typeof Slider == "function")
anim.startAnimating(new Slider(tiddlerElem,false,null,"all"));
else {
removeNode(tiddlerElem);
forceReflow();
}
}
};
config.commands.saveTiddlerHosted1.callback = function(context, userParams) {
var tiddler = store.fetchTiddler(context.title);
if(tiddler) { // if tiddler exists with the old title. (we are renaming)
story.closeTiddler(context.title,false);
store.deleteTiddler(tiddler.title);
tiddler.title = context.newTitle;
store.addTiddler(tiddler);
story.displayTiddler(null,tiddler.title);
story.refreshTiddler(tiddler.title,null,true);
store.notify(tiddler.title,true);
displayMessage("Tiddler Renamed");
} else { //tiddler does not exist so this is a new tiddler.
var newTitle = story.saveTiddler(context.title,userParams.minorUpdate);
if(newTitle)
story.displayTiddler(null,newTitle);
story.closeTiddler(context.title,false);
}
}
function getServerType(fields)
{
if(!fields)
return null;
var serverType = fields['server.type'];
if(!serverType)
serverType = fields['wikiformat'];
if(!serverType)
serverType = config.defaultCustomFields['server.type'];
if(!serverType && typeof RevisionAdaptor != 'undefined' && fields.uuid)
serverType = RevisionAdaptor.serverType;
return serverType;
}
function invokeAdaptor(fnName,param1,param2,context,userParams,callback,fields)
{
var serverType = getServerType(fields);
if(!serverType)
return null;
var adaptor = new config.adaptors[serverType];
if(!adaptor)
return false;
if(!config.adaptors[serverType].prototype[fnName])
return false;
adaptor.openHost(fields['server.host']);
adaptor.openWorkspace(fields['server.workspace']);
var ret = false;
if(param1)
ret = param2 ? adaptor[fnName](param1,param2,context,userParams,callback) : adaptor[fnName](param1,context,userParams,callback);
else
ret = adaptor[fnName](context,userParams,callback);
return ret;
}
//# Returns true if function fnName is available for the serverType specified in fields
//# Used by (eg): config.commands.download.isEnabled
function isAdaptorFunctionSupported(fnName,fields)
{
var serverType = getServerType(fields);
if(!serverType || !config.adaptors[serverType])
return false;
if(!config.adaptors[serverType].isLocal && !fields['server.host'])
return false;
var fn = config.adaptors[serverType].prototype[fnName];
return fn ? true : false;
}
config.commands.revisions.isEnabled = function(tiddler)
{
return isAdaptorFunctionSupported('getTiddlerRevisionList',tiddler.fields);
};
config.commands.revisions.handler = function(event,src,title)
{
var tiddler = store.fetchTiddler(title);
userParams = {};
userParams.tiddler = tiddler;
userParams.src = src;
userParams.dateFormat = config.commands.revisions.dateFormat;
var revisionLimit = 10;
if(!invokeAdaptor('getTiddlerRevisionList',title,revisionLimit,null,userParams,config.commands.revisions.callback,tiddler.fields))
return false;
event.cancelBubble = true;
if(event.stopPropagation)
event.stopPropagation();
return true;
};
config.commands.revisions.callback = function(context,userParams)
// The revisions are returned as tiddlers in the context.revisions array
{
var revisions = context.revisions;
//#displayMessage("config.commands.revisions.callback:"+revisions.length);
popup = Popup.create(userParams.src);
Popup.show(popup,false);
if(revisions.length==0) {
createTiddlyText(createTiddlyElement(popup,'li',null,'disabled'),config.commands.revisions.popupNone);
} else {
revisions.sort(function(a,b) {return a.modified < b.modified ? +1 : -1;});
for(var i=0; i<revisions.length; i++) {
var tiddler = revisions[i];
var modified = tiddler.modified.formatString(context.dateFormat||config.commands.revisions.dateFormat);
var revision = tiddler.fields['server.page.revision'];
var btn = createTiddlyButton(createTiddlyElement(popup,'li'),
config.commands.revisions.revisionTemplate.format([modified,revision,tiddler.modifier]),
tiddler.text||config.commands.revisions.revisionTooltip,
function() {
config.commands.revisions.getTiddlerRevision(this.getAttribute('tiddlerTitle'),this.getAttribute('tiddlerModified'),this.getAttribute('tiddlerRevision'),this);
return false;
},
'tiddlyLinkExisting tiddlyLink');
btn.setAttribute('tiddlerTitle',userParams.tiddler.title);
btn.setAttribute('tiddlerRevision',revision);
btn.setAttribute('tiddlerModified',tiddler.modified.convertToYYYYMMDDHHMM());
if(userParams.tiddler.fields['server.page.revision'] == revision || (!userParams.tiddler.fields['server.page.revision'] && i==0))
btn.className = 'revisionCurrent';
}
}
};
config.commands.revisions.getTiddlerRevision = function(title,modified,revision)
{
var tiddler = store.fetchTiddler(title);
var context = {modified:modified};
return invokeAdaptor('getTiddlerRevision',title,revision,context,null,config.commands.revisions.getTiddlerRevisionCallback,tiddler.fields);
};
config.commands.revisions.getTiddlerRevisionCallback = function(context,userParams)
{
if(context.status) {
var tiddler = context.tiddler;
store.addTiddler(tiddler);
store.notify(tiddler.title, true);
story.refreshTiddler(tiddler.title,1,true);
displayMessage(config.commands.revisions.done);
} else {
displayMessage(context.statusText);
}
};
config.commands.deleteTiddlerHosted.handler = function(event,src,title)
{
var tiddler = store.fetchTiddler(title);
if(!tiddler)
return false;
var deleteIt = true;
if(config.options.chkConfirmDelete)
deleteIt = confirm(this.warning.format([title]));
if(deleteIt) {
var ret = invokeAdaptor('deleteTiddler',title,null,null,null,config.commands.deleteTiddlerHosted.callback,tiddler.fields);
if(ret){
store.removeTiddler(title);
story.closeTiddler(title,true);
autoSaveChanges();
store.setDirty(false);
}
}
return false;
};
config.commands.deleteTiddlerHosted.callback = function(context,userParams)
{
if(context.status) {
displayMessage(config.commands.deleteTiddlerHosted.done + context.title);
} else {
if (context.statusText.indexOf("Not Found") == -1)
displayMessage(context.statusText);
}
};
}//# end of 'install only once'
//}}}
// ccAdaptor //
//{{{
function isLoggedIn(){
return (window.loggedIn == '1')
}
ccTiddlyAdaptor.prototype = new AdaptorBase();
ccTiddlyAdaptor.mimeType = 'application/json';
ccTiddlyAdaptor.serverType = 'cctiddly'; // MUST BE LOWER CASE
ccTiddlyAdaptor.serverParsingErrorMessage = "Error parsing result from server";
ccTiddlyAdaptor.errorInFunctionMessage = "Error in function ccTiddlyAdaptor.%0";
ccTiddlyAdaptor.minHostName = function(host){
return host ? host.replace(/^http:\/\//,'').replace(/\/$/,'') : '';
};
// Convert a page title to the normalized form used in uris
ccTiddlyAdaptor.normalizedTitle = function(title){
return title;
};
// Convert a date in YYYY-MM-DD hh:mm format into a JavaScript Date object
ccTiddlyAdaptor.dateFromEditTime = function(editTime){
var dt = editTime;
return new Date(Date.UTC(dt.substr(0,4),dt.substr(5,2)-1,dt.substr(8,2),dt.substr(11,2),dt.substr(14,2)));
};
ccTiddlyAdaptor.prototype.login = function(context,userParams,callback){
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0/handle/loginFile.php?cctuser=%1&cctpass=%2';
var uri = uriTemplate.format([context.host,context.username,context.password]);
var req = httpReq('GET',uri,ccTiddlyAdaptor.loginCallback,context);
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.loginCallback = function(status,context,responseText,uri,xhr){
if(xhr.status==401){
context.status = false;
}else{
context.status = true;
var c='sessionToken'+"="+responseText;
c+="; expires=Fri, 1 Jan 2811 12:00:00 UTC; host=*";
document.cookie=c;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.register = function(context,userParams,callback){
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0/handle/register.php';
var uri = uriTemplate.format([context.host,context.username,Crypto.hexSha1Str(context.password)]);
var dataTemplate = 'username=&0®_mail=%1&password=%2&password2=%3';
var data = dataTemplate.format([context.username,context.password1,context.password2]);
var req = httpReq('POST', uri,ccTiddlyAdaptor.registerCallback,context,null,data);
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.prototype.rename = function(context, userParams, callback){
context = this.setContext(context,userParams,callback);
var uri = window.url+"handle/renameTiddler.php?otitle="+context.title+"&ntitle="+context.newTitle+"&workspace="+window.workspace;
httpReq('POST', uri,ccTiddlyAdaptor.renameCallback,context,null,null);
};
ccTiddlyAdaptor.renameCallback = function(status,context,responseText,uri,xhr){
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.registerCallback = function(status,context,responseText,uri,xhr){
if(status){
context.status = true;
}else{
context.status = false;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.getWorkspaceList = function(context,userParams,callback){
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0/handle/listWorkspaces.php';
var uri = uriTemplate.format([context.host]);
var req = httpReq('GET', uri,ccTiddlyAdaptor.getWorkspaceListCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.getWorkspaceListCallback = function(status,context,responseText,uri,xhr){
context.status = false;
context.workspaces = [];
context.statusText = ccTiddlyAdaptor.errorInFunctionMessage.format(['getWorkspaceListCallback']);
if(status){
try{
eval('var workspaces=' + responseText);
}catch (ex){
context.statusText = exceptionText(ex,ccTiddlyAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
for (var i=0; i < workspaces.length; i++){
context.workspaces.push({title:workspaces[i]})
}
context.status = true;
}else{
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.getTiddlerList = function(context,userParams,callback){
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0/handle/listTiddlers.php?workspace=%1';
var uri = uriTemplate.format([context.host,context.workspace]);
var req = httpReq('GET', uri,ccTiddlyAdaptor.getTiddlerListCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.getTiddlerListCallback = function(status,context,responseText,uri,xhr){
context.status = false;
context.statusText = ccTiddlyAdaptor.errorInFunctionMessage.format(['getTiddlerListCallback']);
if(status){
try{
eval('var tiddlers=' + responseText);
}catch (ex){
context.statusText = exceptionText(ex,ccTiddlyAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
var list = [];
for(var i=0; i < tiddlers.length; i++){
var tiddler = new Tiddler(tiddlers[i]['title']);
tiddler.fields['server.page.revision'] = tiddlers[i]['revision'];
list.push(tiddler);
}
context.tiddlers = list;
context.status = true;
}else{
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.generateTiddlerInfo = function(tiddler){
var info ={};
var host = this && this.host ? this.host : this.fullHostName(tiddler.fields['server.host']);
var bag = tiddler.fields['server.bag']
var workspace = tiddler.fields['server.workspace']
var uriTemplate = '%0/%1/#%2';
info.uri = uriTemplate.format([host,workspace,tiddler.title]);
return info;
};
ccTiddlyAdaptor.prototype.getTiddlerRevision = function(title,revision,context,userParams,callback){
context = this.setContext(context,userParams,callback);
if(revision)
context.revision = revision;
return this.getTiddler(title,context,userParams,callback);
};
ccTiddlyAdaptor.prototype.getTiddler = function(title,context,userParams,callback){
context = this.setContext(context,userParams,callback);
if(title)
context.title = title;
if(context.revision){
var uriTemplate = '%0/handle/revisionDisplay.php?title=%2&workspace=%1&revision=%3';
}else{
var uriTemplate = '%0/handle/getTiddler.php?title=%2&workspace=%1';
}
uri = uriTemplate.format([context.host,context.workspace,ccTiddlyAdaptor.normalizedTitle(title),context.revision]);
context.tiddler = new Tiddler(title);
context.tiddler.fields['server.type'] = ccTiddlyAdaptor.serverType;
context.tiddler.fields['server.host'] = ccTiddlyAdaptor.minHostName(context.host);
context.tiddler.fields['server.workspace'] = context.workspace;
var req = httpReq('GET', uri,ccTiddlyAdaptor.getTiddlerCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.getTiddlerCallback = function(status,context,responseText,uri,xhr){
context.status = false;
context.statusText = ccTiddlyAdaptor.errorInFunctionMessage.format(['getTiddlerCallback']);
if(status){
var info=[]
try{
eval('info=' + responseText);
}catch (ex){
context.statusText = exceptionText(ex,ccTiddlyAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
context.tiddler.text = info['text'];
context.tiddler.tags = info['tags'].split(" ");
context.tiddler.fields['server.page.revision'] = info['revision'];
context.tiddler.modifier = info['modifier'];
context.tiddler.modified = Date.convertFromYYYYMMDDHHMM(info['modified']);
context.tiddler.created = Date.convertFromYYYYMMDDHHMM(info['created']);
context.status = true;
}else{
context.statusText = xhr.statusText;
if(context.callback)
context.callback(context,context.userParams);
return;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.getTiddlerRevisionList = function(title,limit,context,userParams,callback){
context = this.setContext(context,userParams,callback);
context.title = title;
context.revisions = [];
var tiddler = store.fetchTiddler(title);
var encodedTitle = encodeURIComponent(title);
var uriTemplate = '%0/handle/revisionList.php?workspace=%1&title=%2';
var host = this.fullHostName(this.host);
var workspace = context.workspace ? context.workspace : tiddler.fields['server.workspace'];
var uri = uriTemplate.format([host,workspace,encodedTitle]);
var req = httpReq('GET', uri,ccTiddlyAdaptor.getTiddlerRevisionListCallback,context);
};
ccTiddlyAdaptor.getTiddlerRevisionListCallback = function(status,context,responseText,uri,xhr){
if(responseText.indexOf('<!DOCTYPE html')==1)
status = false;
if(xhr.status=="204")
status = false;
context.status = false;
if(status){
var r = responseText;
if(r != '-' && r.trim() != 'revision not found'){
var revs = r.split('\n');
for(var i=0; i<revs.length; i++){
var parts = revs[i].split(' ');
if(parts.length>1){
var tiddler = new Tiddler(context.title);
tiddler.modified = Date.convertFromYYYYMMDDHHMM(parts[0]);
tiddler.fields['server.page.revision'] = String(parts[1]);
tiddler.modifier = String(parts[2]);
tiddler.fields['server.host'] = ccTiddlyAdaptor.minHostName(context.host);
tiddler.fields['server.type'] = ccTiddlyAdaptor.serverType;
context.revisions.push(tiddler);
}
}
}
context.revisions.sort(function(a,b){return a.modified<b.modified?+1:-1;});
context.status = true;
}else{
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
ccTiddlyAdaptor.prototype.putTiddler = function(tiddler,context,userParams,callback){
context = this.setContext(context,userParams,callback);
context.title = tiddler.title;
var recipeuriTemplate = '%0/handle/save.php';
var host = context.host ? context.host : this.fullHostName(tiddler.fields['server.host']);
var uri = recipeuriTemplate.format([host,context.workspace,tiddler.title]);
var d = new Date();
d.setTime(Date.parse(tiddler['modified']));
d = d.convertToYYYYMMDDHHMM();
var fieldString = "";
for (var name in tiddler.fields){
if (String(tiddler.fields[name]))
fieldString += name +"='"+tiddler.fields[name]+"' ";
}
// Freds SEO Code
if(workspace)
var breaker = "/";
else
var breaker = "";
var el = createTiddlyElement(document.body, "div", "ccTiddlyTMP", null, null, { "style.display": "none" });
var formatter = new Formatter(config.formatters);
var wikifier = new Wikifier(tiddler.text,formatter,null,tiddler);
wikifier.isStatic = true;
wikifier.subWikify(el);
delete formatter;
var links = el.getElementsByTagName("a");
for(var i = 0; i < links.length; i++) {
var tiddlyLink = links[i].getAttribute("tiddlyLink");
if(tiddlyLink) {
if(hasClass(links[i], "tiddlyLinkNonExisting")) { // target tiddler does not exist
links[i].href = "#";
} else {
links[i].href = url+ workspace + breaker +tiddlyLink + ".html";
}
}
}
// End Freds SEO Code
if(tiddler.fields['server.page.revision']==1)
tiddler.fields['server.page.revision'] = 10000;
else
tiddler.fields['server.page.revision'] = parseInt(tiddler.fields['server.page.revision'],10)+1;
if(!context.otitle)
var otitle = tiddler.title;
else
var otitle = context.otitle;
var payload = "workspace="+window.workspace+"&otitle="+encodeURIComponent(otitle)+"&title="+encodeURIComponent(tiddler.title) + "&modified="+tiddler.modified.convertToYYYYMMDDHHMM()+"&modifier="+tiddler.modifier + "&tags="+tiddler.getTags()+"&revision="+encodeURIComponent(tiddler.fields['server.page.revision']) + "&fields="+encodeURIComponent(fieldString)+
"&body="+encodeURIComponent(tiddler.text)+"&wikifiedBody="+encodeURIComponent(el.innerHTML)+"";
var req = httpReq('POST', uri,ccTiddlyAdaptor.putTiddlerCallback,context,{'Content-type':'application/x-www-form-urlencoded', "Content-length": payload.length},payload,"application/x-www-form-urlencoded");
removeNode(el);
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.center = function(el){
var size = this.getsize(el);
el.style.left = (Math.round(findWindowWidth()/2) - (size.width /2) + findScrollX())+'px';
el.style.top = (Math.round(findWindowHeight()/2) - (size.height /2) + findScrollY())+'px';
}
ccTiddlyAdaptor.getsize = function (el){
var x ={};
x.width = el.offsetWidth || el.style.pixelWidth;
x.height = el.offsetHeight || el.style.pixelHeight;
return x;
}
ccTiddlyAdaptor.showCloak = function(){
var cloak = document.getElementById('backstageCloak');
if (config.browser.isIE){
cloak.style.height = Math.max(document.documentElement.scrollHeight,document.documentElement.offsetHeight);
cloak.style.width = document.documentElement.scrollWidth;
}
cloak.style.display = "block";
}
ccTiddlyAdaptor.hideError = function(){
var box = document.getElementById('errorBox');
box.parentNode.removeChild(box);
document.getElementById('backstageCloak').style.display = "";
}
ccTiddlyAdaptor.handleError = function(error_code){
setStylesheet(
"#errorBox .button{padding:0.5em 1em; border:1px solid #222; background-color:#ccc; color:black; margin-right:1em;}\n"+
"html > body > #backstageCloak{height:100%;}"+
"#errorBox{border:1px solid #ccc;background-color: #eee; color:#111;padding:1em 2em; z-index:9999;}",'errorBoxStyles');
var box = document.getElementById('errorBox') || createTiddlyElement(document.body,'div','errorBox');
var error = ccTiddlyAdaptor.errorTitleNotSaved;
switch(error_code){
case 401:
error += ccTiddlyAdaptor.errorTextSessionExpired;
break;
case 409:
error += ccTiddlyAdaptor.errorTextConflict;
break;
default:
error += ccTiddlyAdaptor.errorTextUnknown+"<br />"+ccTiddlyAdaptor.msgErrorCode+error_code;
}
box.innerHTML = " <a style='float:right' href='javascript:onclick=ccTiddlyAdaptor.hideError()'>"+ccTiddlyAdaptor.errorClose+"</a><p>"+error+"</p><br/><br/>";
createTiddlyButton(box,ccTiddlyAdaptor.buttonOpenNewWindow,null,function(e){ window.open (window.location,"mywindow"); return false;});
createTiddlyElement(box,"br");
createTiddlyElement(box,"br");
createTiddlyButton(box,ccTiddlyAdaptor.buttonHideThisMessage,null,function(){ccTiddlyAdaptor.hideError();});
box.style.position = 'absolute';
ccTiddlyAdaptor.center(box);
ccTiddlyAdaptor.showCloak();
}
ccTiddlyAdaptor.putTiddlerCallback = function(status,context,responseText,uri,xhr){
context.status = false;
if(status){
context.status = true;
}else{
context.status = false;
if(xhr.status == 401 || xhr.status==409){
ccTiddlyAdaptor.handleError(xhr.status);
}else{
ccTiddlyAdaptor.handleError(xhr.status);
context.statusText = xhr.statusText;
}
}
if(context.callback){
context.callback(context,context.userParams);
}
};
ccTiddlyAdaptor.prototype.deleteTiddler = function(title,context,userParams,callback){
context = this.setContext(context,userParams,callback);
context.title = title;
title = encodeURIComponent(title);
var host = this && this.host ? this.host : this.fullHostName(tiddler.fields['server.host']);
var uriTemplate = '%0/handle/delete.php?workspace=%1&title=%2';
var uri = uriTemplate.format([host,context.workspace,title]);
var req = httpReq('POST', uri,ccTiddlyAdaptor.deleteTiddlerCallback,context);
return typeof req == 'string' ? req : true;
};
ccTiddlyAdaptor.deleteTiddlerCallback = function(status,context,responseText,uri,xhr){
if(status){
context.status = true;
}else{
context.status = false;
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
config.adaptors[ccTiddlyAdaptor.serverType] = ccTiddlyAdaptor;
//}}}
//}}}
/***
|''Name''|ccTiddlyPlugin|
|''Description''|The ccTiddlyPlugin macro contains all the macros necessary to run ccTiddly.|
|''Author''|Simon McManus|
|''Contributors''|Simon McManus, James Lelyveld|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/serversides/cctiddly/tiddlers/plugins/ccTiddlyPlugins.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/serversides/cctiddly/tiddlers/plugins/ccTiddlyPlugins.js|
|''Feedback''|http://groups.google.com/group/ccTiddly|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]] |
|''~CoreVersion:''|2.2.0|
|''Date:''|Nov 6, 2008|
|''Version:''|0.1|
!Usage
{{{
<<ccAbout>>
<<ccAdmin>>
<<ccCreateWorkspace>>
<<ccEditWorkspace>>
<<ccFile>>
<<ccLogin>>
<<ccLoginStatus>>
<<ccRegister>>
<<ccStats>>
}}}
***/
//{{{
config.backstageTasks.remove("upgrade");
config.backstageTasks.remove("save");
config.backstageTasks.remove("sync");
// ccAbout //
config.backstageTasks.push(config.macros.ccAbout.buttonBackstageText);
merge(config.tasks,{about:{text: config.macros.ccAbout.buttonBackstageText,tooltip: config.macros.ccAbout.buttonBackstageTooltip,content: '<<ccAbout>>'}});
config.macros.ccAbout.handler=function(place,macroName,params,wikifier,paramString,tiddler,errorMsg){
var w = new Wizard();
var me = config.macros.ccAbout;
w.createWizard(place,me.stepAboutTitle);
w.addStep(null, me.stepAboutTextStart + window.ccTiddlyVersion + "<br /><br />" + me.stepAboutTextEnd);
};
//}}}
// ccAdmin //
//{{{
config.macros.ccAdmin.handler = function(place,macroName,params,wikifier,paramString,tiddler, errorMsg){
var w = new Wizard();
w.createWizard(place,config.macros.ccAdmin.WizardTitleText);
config.macros.ccAdmin.refresh(w);
};
config.macros.ccAdmin.refresh= function(w){
params = {};
params.w = w;
params.e = this;
me = config.macros.ccAdmin;
doHttp('POST',url+'/handle/workspaceAdmin.php','action=LISTALL&workspace='+workspace,null,null,null,config.macros.ccAdmin.listAllCallback,params);
w.setButtons([
{caption: me.buttonDeleteText, tooltip: me.buttonDeleteTooltip, onClick: function(w){
config.macros.ccAdmin.delAdminSubmit(null, params);
return false;
}},
{caption: me.buttonAddText, tooltip: me.buttonAddTooltip, onClick: function(w){
config.macros.ccAdmin.addAdminDisplay(null, params); return false } }]);
};
config.macros.ccAdmin.delAdminSubmit = function(e, params){
var listView = params.w.getValue("listView");
var rowNames = ListView.getSelectedRows(listView);
var delUsers = "";
for(var e=0; e < rowNames.length; e++)
delUsers += rowNames[e]+",";
doHttp('POST',url+'/handle/workspaceAdmin.php','action=DELETEADMIN&username='+delUsers+'&workspace='+workspace,null,null,null,config.macros.ccAdmin.addAdminCallback,params);
return false;
};
config.macros.ccAdmin.addAdminDisplay = function(e, params){
doHttp('POST',url+'/handle/workspaceAdmin.php','action=LISTWORKSPACES',null,null,null,config.macros.ccAdmin.listWorkspaces,params);
};
config.macros.ccAdmin.listWorkspaces = function(status,params,responseText,uri,xhr){
var frm = createTiddlyElement(null,'form',null,null);
var me = config.macros.ccAdmin;
frm.onsubmit = config.macros.ccAdmin.addAdminSubmit;
params.w.addStep(me.stepAddTitle,"<input type='hidden' name='admin_placeholder'/>"+me.labelUsername+"<input name=adminUsername><br />"+me.labelWorkspace+"<select name=workspaceName />");
var workspaces = eval('[ '+responseText+' ]');
for(var t=0; t<workspaces.length; t++) {
var o = createTiddlyElement(params.w.formElem.workspaceName, "option", null, null, workspaces[t]);
o.value=workspaces[t];
if(workspaces[t] == workspace)
o.selected = true;
}
params.w.formElem.admin_placeholder.parentNode.appendChild(frm);
params.w.setButtons([
{caption: me.buttonCancelText, tooltip: me.buttonCancelTooltip, onClick: function(w){ config.macros.ccAdmin.refresh(params.w) } },
{caption: me.buttonCreateText, tooltip: me.buttonCreateTooltip, onClick: function(){config.macros.ccAdmin.addAdminSubmit(null, params); } }
]);
};
config.macros.ccAdmin.addAdminSubmit = function(e, params){
doHttp('POST',url+'/handle/workspaceAdmin.php','&add_username='+params.w.formElem.adminUsername.value+'&action=addNew&workspace='+params.w.formElem.workspaceName[params.w.formElem.workspaceName.selectedIndex].value,null,null,null,config.macros.ccAdmin.addAdminCallback,params);
return false;
};
config.macros.ccAdmin.listAllCallback = function(status,params,responseText,uri,xhr) {
var me = config.macros.ccAdmin;
var out = "";
var adminUsers = [];
if(xhr.status == 403){
var html ='';
params.w.addStep(me.stepErrorText+workspace, me.stepErrorTitle);
params.w.setButtons([]);
return false;
}
try{
var a = eval(responseText);
for(var e=0; e < a.length; e++){
out += a[e].username;
adminUsers.push({
name: a[e].username,
lastVisit:a[e].lastVisit});
}
}catch(ex){
params.w.addStep(" "+workspace, me.stepNoAdminTitle);
params.w.setButtons([
{caption: me.buttonCreateText, tooltip: me.buttonCreateTooltip, onClick: function(){ config.macros.ccAdmin.addAdminDisplay(null, params)}}]);
return false;
}
var html ='<input type="hidden" name="markList"></input>';
params.w.addStep(me.stepManageWorkspaceTitle+workspace, html);
var markList = params.w.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
var listView = ListView.create(listWrapper,adminUsers,config.macros.ccAdmin.listAdminTemplate);
params.w.setValue("listView",listView);
};
config.macros.ccAdmin.addAdminCallback = function(status,params,responseText,uri,xhr) {
config.macros.ccAdmin.refresh(params.w);
};
// ccAutoSave //
//{{{
//# Ensure that the plugin is only installed once.
if(!version.extensions.ccTiddlyAutoSavePlugin) {
version.extensions.ccTiddlyAutoSavePlugin = {installed:true};
ccTiddlyAutoSave.putCallback = function(context, userParams){
tiddler = context.tiddler;
if (context.status){
if (context.otitle != tiddler.title){
var ret = invokeAdaptor('deleteTiddler',context.otitle,null,null,null,config.commands.deleteTiddlerHosted.callback,tiddler.fields);
}
displayMessage(ccTiddlyAutoSave.msgSaved + tiddler.title);
tiddler.clearChangeCount();
}else{
displayMessage(ccTiddlyAutoSave.msgError + tiddler.title + ' ' + context.statusText);
tiddler.incChangeCount();
}
};
TiddlyWiki.prototype.orig_saveTiddler = TiddlyWiki.prototype.saveTiddler; //hijack
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created){
var tiddler = this.orig_saveTiddler(title,newTitle,newBody,modifier,modified,tags,fields,false,created); //
// var tiddler = this.fetchTiddler(title); //And then I get it
var adaptor = new config.adaptors['cctiddly'];
// put the tiddler and deal with callback
tiddler.fields['server.host'] = window.url;
tiddler.fields['server.type'] = config.defaultCustomFields['server.type'];
tiddler.fields['server.workspace'] = window.workspace;
tiddler.clearChangeCount();
context = {};
context.tiddler = tiddler;
context.otitle = title;
context.workspace = window.workspace;
context.host = window.url;
req = adaptor.putTiddler(tiddler, context, {}, ccTiddlyAutoSave.putCallback);
if(req)
store.setDirty(false);
return req ? tiddler : false;
};
} //# end of 'install only once'
//}}}
// ccCreateWorkspace //
//{{{
if(isLoggedIn()){
config.backstageTasks.push(config.macros.ccCreateWorkspace.buttonCreateText);
merge(config.tasks,{create: {text: config.macros.ccCreateWorkspace.buttonCreateText, tooltip: config.macros.ccCreateWorkspace.buttonCreateTooltip, content:'<<ccCreateWorkspace>>'}});
}
config.macros.ccCreateWorkspace.setStatus=function(w,element,text){
var label_var = w.getElement(element);
removeChildren(label_var.previousSibling);
var label = document.createTextNode(text);
label_var.previousSibling.insertBefore(label,null);
}
config.macros.ccCreateWorkspace.workspaceNameKeyPress=function(w){
params={};
params.w = w;
doHttp('POST',url+'/handle/lookupWorkspaceName.php',"ccWorkspaceLookup="+w.formElem["workspace_name"].value+"&free=1",null,null,null,config.macros.ccCreateWorkspace.workspaceNameCallback,params);
return false;
};
config.macros.ccCreateWorkspace.workspaceNameCallback=function(status,params,responseText,uri,xhr){
var me = config.macros.ccCreateWorkspace;
if(responseText > 0){{
config.macros.register.setStatus(params.w, "workspace_error", me.errorWorkspaceNameInUse);
config.macros.register.setStatus(params.w, "workspace_url", "");
}}else{
config.macros.register.setStatus(params.w, "workspace_error", me.msgWorkspaceAvailable);
if (window.useModRewrite == 1)
config.macros.register.setStatus(params.w, "workspace_url", url+''+params.w.formElem["workspace_name"].value);
else
config.macros.register.setStatus(params.w, "workspace_url", url+'?workspace='+params.w.formElem["workspace_name"].value);
}
};
config.macros.ccCreateWorkspace.handler = function(place,macroName,params,wikifier,paramString,tiddler, errorMsg){
if (window.workspacePermission.canCreateWorkspace!=1) {
createTiddlyElement(place,'div', null, "annotation", config.macros.ccCreateWorkspace.errorPermissions);
return null;
}
var me = config.macros.ccCreateWorkspace;
var w = new Wizard();
w.createWizard(place,me.wizardTitle);
w.addStep(me.stepTitle, me.stepCreateHtml);
w.formElem["workspace_name"].onkeyup=function() {me.workspaceNameKeyPress(w);};
w.setButtons([
{caption: me.buttonCreateWorkspaceText, tooltip: me.buttonCreateWorkspaceTooltip, onClick:function(){config.macros.ccCreateWorkspace.createWorkspaceOnSubmit(w);}
}]);
};
config.macros.ccCreateWorkspace.createWorkspaceOnSubmit = function(w){
var params = {};
if(window.useModRewrite == 1)
params.url = url+w.formElem["workspace_name"].value;
else
params.url = url+'?workspace='+w.formElem["workspace_name"].value;
var loginResp = doHttp('POST',url+'?&workspace='+w.formElem["workspace_name"].value+"/",'&ccCreateWorkspace=' + encodeURIComponent(w.formElem["workspace_name"].value)+'&ccAnonPerm='+encodeURIComponent("AADD"),null,null,null,config.macros.ccCreateWorkspace.createWorkspaceCallback,params);
return false;
};
config.macros.ccCreateWorkspace.createWorkspaceCallback = function(status,params,responseText,uri,xhr) {
if(xhr.status==201){
window.location = params.url;
}else if(xhr.status == 200){
displayMessage(config.macros.ccCreateWorkspace.errorWorkspaceNameInUse);
}else if(xhr.status == 403){
displayMessage(config.macros.ccCreateWorkspace.errorPermissions);
}else{
displayMessage(responseText);
}
};
//}}}
// ccEditWorkspace //
//{{{
config.macros.ccEditWorkspace.handler = function(place, macroName, params, wikifier, paramString, tiddler){
var me = config.macros.ccEditWorkspace;
if(workspacePermission.owner !=1){
createTiddlyElement(place,'div', null, "annotation", me.errorTextPermissionDenied);
return null;
}
var w = new Wizard();
w.createWizard(place, this.WizardTitleText);
var booAdmin = false;
var booUser = false;
var booAnon = false;
// Check which colums to display
for(i = 0; i <= params.length - 1; i++){
switch (params[i].toLowerCase()) {
case 'admin':
booAdmin = true;
break;
case 'user':
booUser = true;
break;
case 'anon':
booAnon = true;
break;
}
}
// if nothing passed show all
if(!booAdmin && !booUser && !booAnon){
booAdmin = true;
booUser = true;
booAnon = true;
}
var tableBodyBuffer = new Array();
tableBodyBuffer.push('<table border=0px class="listView twtable">');
tableBodyBuffer.push('<tr">');
tableBodyBuffer.push('<th>' + this.stepLabelPermission + '</th>');
if(booAnon){
tableBodyBuffer.push('<th>' + this.stepLabelAnon + '</th>');
}
if(booUser){
tableBodyBuffer.push('<th>' + this.stepLabelUser + '</th>');
}
if(booAdmin){
tableBodyBuffer.push('<th>' + this.stepLabelAdmin + '</th>');
}
tableBodyBuffer.push('</tr>');
tableBodyBuffer.push('<tr>')
tableBodyBuffer.push('<th align="right">'+this.stepLabelRead+'</th>');
if(booAnon){
tableBodyBuffer.push('<td><input name="anR" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.anonR == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booUser){
tableBodyBuffer.push('<td><input name="usR" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.userR == 1 ? 'checked' : '');
tableBodyBuffer.push('></input></td>');
}
if(booAdmin){
tableBodyBuffer.push('<td><input name="adR" class="checkInput" type="checkbox" checked disabled></input></td>');
}
tableBodyBuffer.push('</tr>');
tableBodyBuffer.push('<tr>');
tableBodyBuffer.push('<th align="right">' + this.stepLabelCreate + '</th>');
if(booAnon){
tableBodyBuffer.push('<td><input name="anC" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.anonC == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booUser){
tableBodyBuffer.push('<td><input name="usC" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.userC == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booAdmin){
tableBodyBuffer.push('<td><input name="adC" class="checkInput" type="checkbox" checked disabled></input></td>');
}
tableBodyBuffer.push('</tr>');
tableBodyBuffer.push('<tr>');
tableBodyBuffer.push('<th align="right">' + this.stepLabelUpdate + '</th>');
if(booAnon){
tableBodyBuffer.push('<td><input name="anU" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.anonU == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booUser){
tableBodyBuffer.push('<td><input name="usU" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.userU == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booAdmin){
tableBodyBuffer.push('<td><input name="adU" class="checkInput" type="checkbox" checked disabled></input></td>');
}
tableBodyBuffer.push('</tr>');
tableBodyBuffer.push('<tr>');
tableBodyBuffer.push('<th align="right">' + this.stepLabelDelete + '</th>');
if(booAnon){
tableBodyBuffer.push('<td><input name="anD" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.anonD == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booUser){
tableBodyBuffer.push('<td><input name="usD" class="checkInput" type="checkbox" ');
tableBodyBuffer.push(workspacePermission.userD == 1 ? 'checked' : '');
tableBodyBuffer.push(' ></input></td>');
}
if(booAdmin){
tableBodyBuffer.push('<td><input name="adD" class="checkInput" type="checkbox" checked disabled></input></td>');
}
tableBodyBuffer.push('</tr>');
tableBodyBuffer.push('</table>');
var stepHTML = tableBodyBuffer.join('');
w.addStep(this.stepEditTitle,stepHTML);
w.setButtons([
{caption: this.buttonSubmitCaption, tooltip: this.buttonSubmitToolTip, onClick: function() {me.ewSubmit(place, macroName, params, wikifier, paramString, tiddler,w,booAnon,booUser);}
}]);
};
config.macros.ccEditWorkspace.ewSubmit = function(place, macroName, params2, wikifier, paramString, tiddler,w, booAnon, booUser){
var trueStr = "A";
var falseStr = "U";
var anon = '';
var user = '';
if(booAnon){
var anonBuffer = new Array();
anonBuffer.push(w.formElem['anR'].checked ? trueStr : falseStr);
anonBuffer.push(w.formElem['anC'].checked ? trueStr : falseStr);
anonBuffer.push(w.formElem['anU'].checked ? trueStr : falseStr);
anonBuffer.push(w.formElem['anD'].checked ? trueStr : falseStr);
anon = anonBuffer.join('');
}
if(booUser){
var userBuffer = new Array();
userBuffer.push(w.formElem['usR'].checked ? trueStr : falseStr);
userBuffer.push(w.formElem['usC'].checked ? trueStr : falseStr);
userBuffer.push(w.formElem['usU'].checked ? trueStr : falseStr);
userBuffer.push(w.formElem['usD'].checked ? trueStr : falseStr);
user = userBuffer.join('');
}
var params = new Array();
params.w = w;
params.u = user;
params.a = anon;
params.p = place;
params.m = macroName;
params.pr = params2;
params.wi = wikifier;
params.ps = paramString;
params.t = tiddler;
doHttp('POST', url + '/handle/updateWorkspace.php', 'ccCreateWorkspace=' + encodeURIComponent(workspace) + '&ccAnonPerm=' + encodeURIComponent(anon) + '&ccUserPerm=' + encodeURIComponent(user), null, null, null, config.macros.ccEditWorkspace.editWorkspaceCallback, params);
return false;
}
config.macros.ccEditWorkspace.editWorkspaceCallback = function(status,params,responseText,uri,xhr){
var w = params.w;
var me = config.macros.ccEditWorkspace;
if(xhr.status == 200){
// use the incoming parameters to set the workspace permission variables.
if (params.a != ''){
workspacePermission.anonR = (params.a.substr(0,1)=='A'?1:0);
workspacePermission.anonC = (params.a.substr(1,1)=='A'?1:0);
workspacePermission.anonU = (params.a.substr(2,1)=='A'?1:0);
workspacePermission.anonD = (params.a.substr(3,1)=='A'?1:0);
}
if (params.u != ''){
workspacePermission.userR = (params.u.substr(0,1)=='A'?1:0);
workspacePermission.userC = (params.u.substr(1,1)=='A'?1:0);
workspacePermission.userU = (params.u.substr(2,1)=='A'?1:0);
workspacePermission.userD = (params.u.substr(3,1)=='A'?1:0);
}
w.addStep('',responseText);
// want to set a back button here
w.setButtons([
{caption: me.button1SubmitCaption, tooltip: me.button1SubmitToolTip, onClick: function() {config.macros.ccEditWorkspace.refresh(params.p, params.m, params.pr, params.wi, params.ps, params.t);}}
]);
}else{
w.addStep(me.step2Error+': ' + xhr.status,config.macros.ccEditWorkspace.errorUpdateFailed);
}
return false;
};
config.macros.ccEditWorkspace.refresh = function(place, macroName, params, wikifier, paramString, tiddler){
removeChildren(place);
config.macros.ccEditWorkspace.handler(place, macroName, params, wikifier, paramString, tiddler);
}
//}}}
// ccFile //
//{{{
var iFrameLoad=function(w){
var uploadIframe = document.getElementById('uploadIframe');
var a = createTiddlyElement(null, "div");
a.innerHTML = uploadIframe.contentDocument.body.innerHTML;
removeChildren(w.formElem.placeholder);
w.formElem.placeholder.parentNode.appendChild(a);
var statusArea = w.formElem.placeholder;
document.getElementById("ccfile").value="";
};
config.macros.ccFile.handler=function(place,macroName,params,wikifier,paramString,tiddler, errorMsg){
var w = new Wizard();
w.createWizard(place,config.macros.ccFile.wizardTitleText);
config.macros.ccFile.refresh(w);
};
config.macros.ccFile.refresh=function(w){
params = {};
params.w = w;
params.e = this;
var me = config.macros.ccFile;
doHttp('GET',url+'/handle/listFiles.php?workspace='+workspace,'',null,null,null,config.macros.ccFile.listAllCallback,params);
w.setButtons([
{caption: me.buttonDeleteText, tooltip: me.buttonDeleteTooltip, onClick: function(w){
config.macros.ccFile.delFileSubmit(null, params);
return false;
}},
{caption: me.buttonUploadText, tooltip: me.buttonUploadTooltip, onClick: function(e){
config.macros.ccFile.addFileDisplay(null, params); return false
} }
]);
};
config.macros.ccFile.delFileSubmit=function(e, params) {
var listView = params.w.getValue("listView");
var rowNames = ListView.getSelectedRows(listView);
for(var e=0; e < rowNames.length; e++)
doHttp('POST',url+'/handle/listFiles.php','action=DELETEFILE&file='+rowNames[e]+'&workspace='+workspace,null,null,null,config.macros.ccFile.delFileCallback,params);
return false;
};
config.macros.ccFile.delFileCallback=function(status,params,responseText,uri,xhr){
config.macros.ccFile.refresh(params.w);
};
config.macros.ccFile.addFileDisplay = function(e, params){
var frm = params.w.formElem;
if(navigator.appName=="Microsoft Internet Explorer"){
encType = frm.getAttributeNode("enctype");
encType.value = "multipart/form-data";
}
frm.setAttribute("enctype","multipart/form-data");
frm.setAttribute("method","POST");
frm.action=window.url+"/handle/upload.php";
frm.id="ccUpload";
frm.target="uploadIframe";
frm.name = "uploadForm";
frm.parentNode.appendChild(frm);
params.w.addStep("ss", "<input id='ccfile' class='input' type='file' name='userFile'/>"+"<input type='hidden' name='placeholder'/>");
var workspaceName=createTiddlyElement(null,'input','workspaceName','workspaceName');
workspaceName .setAttribute('name','workspace');
workspaceName.type="HIDDEN";
workspaceName.value=workspace;
frm.appendChild(workspaceName);
createTiddlyElement(frm,'br');
var saveTo=createTiddlyElement(null,"input","saveTo","saveTo");
var iframe=document.createElement("iframe");
iframe.style.display="none";
iframe.id='uploadIframe';
iframe.name='uploadIframe';
iframe.onload = function() {
iFrameLoad(params.w);
}
frm.appendChild(iframe);
createTiddlyElement(frm,"div",'uploadStatus');
params.w.setButtons([
{caption: config.macros.ccFile.buttonCancelText, tooltip: config.macros.ccFile.buttonCancelTooltip, onClick: function(){config.macros.ccFile.refresh(params.w);}
},
{caption: config.macros.ccFile.buttonUploadText, tooltip: config.macros.ccFile.buttonUploadTooltip, onClick: function(){params.w.formElem.submit();}
}]);
};
function addOption(selectbox,text,value ){
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}
config.macros.ccFileImageBox = function(image){
var full = image.src;
setStylesheet(
"#errorBox .button {padding:0.5em 1em; border:1px solid #222; background-color:#ccc; color:black; margin-right:1em;}\n"+
"html > body > #backstageCloak {height:"+window.innerHeight*2+"px;}"+
"#errorBox {border:1px solid #ccc;background-color: #fff; color:#111;padding:1em 2em; z-index:9999;}",'errorBoxStyles');
var box = document.getElementById('errorBox') || createTiddlyElement(document.body,'div','errorBox');
box.innerHTML = "<a style='float:right' href='javascript:onclick=ccTiddlyAdaptor.hideError()'>"+ccTiddlyAdaptor.errorClose+"</a><h3>"+image.src+"</h3><br />";
box.style.position = 'absolute';
box.style.width= "800px";
var img = createTiddlyElement(box, "img");
img.src = full;
ccTiddlyAdaptor.center(box);
ccTiddlyAdaptor.showCloak();
}
config.macros.ccFile.listAllCallback = function(status,params,responseText,uri,xhr){
var me = config.macros.ccFile;
var out = "";
var adminUsers = [];
if(xhr.status!=200){
params.w.addStep(me.errorPermissionDeniedTitle, me.errorPermissionDeniedView);
return true;
}
try{
var a = eval(responseText);
for(var e=0; e < a.length; e++){
out += a[e].username;
adminUsers.push({
htmlName: "<html><a href='"+a[e].url+"' target='new'>"+a[e].filename+"</a></html>",
name: a[e].filename,
wikiText:'<html><img onclick="config.macros.ccFileImageBox(this)"; src="'+a[e].url+'" style="width: 70px; "/></html>',
lastVisit:a[e].lastVisit,
fileSize:a[e].fileSize
});
}
}catch (ex){
params.w.setButtons([
{caption: me.buttonUploadText, tooltip: me.buttonUploadTooltip, onClick: function(w){
config.macros.ccFile.addFileDisplay(e, params);
} }]);
}
params.w.addStep(me.wizardStepText+workspace, "<input type='hidden' name='markList'></input>");
var markList = params.w.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
var listView = ListView.create(listWrapper,adminUsers,config.macros.ccFile.listAdminTemplate);
//params.w.setValue("listAdminView",listAdminView);
params.w.setValue("listView",listView);
};
config.macros.ccFile.addFileCallback = function(status,params,responseText,uri,xhr){
config.macros.ccFile.refresh(params.w);
};
//}}}
// ccChangePassword //
// {{{
config.macros.ccChangePassword.handler=function(place,macroName,params,wikifier,paramString,tiddler,errorMsg){
var w = new Wizard();
var me = config.macros.ccChangePassword;
w.createWizard(place,me.title);
w.addStep(me.subTitle+cookieString(document.cookie).txtUserName,me.step1Html);
w.setButtons([
{caption: me.buttonChangeText, tooltip: me.buttonChangeToolTip, onClick: function(){config.macros.ccChangePassword.doPost(w); } }
]);
};
config.macros.ccChangePassword.doPost = function (w) {
me = config.macros.ccChangePassword;
if(!w.formElem.new1.value || !w.formElem.new2.value || !w.formElem.old.value) {
displayMessage(me.noticePasswordUpdateFailed);
return false;
}
if(w.formElem.new1.value != w.formElem.new2.value){
displayMessage(me.noticePasswordsNoMatch);
return false;
}
doHttp("POST", url+"handle/changePassword.php", "&new1="+Crypto.hexSha1Str(w.formElem.new1.value)+"&new2="+Crypto.hexSha1Str(w.formElem.new2.value)+"&old1="+Crypto.hexSha1Str(w.formElem.old.value),null,null,null,config.macros.ccChangePassword.callback);
}
config.macros.ccChangePassword.callback = function(status,context,responseText,uri,xhr) {
if(xhr.status == 304)
displayMessage(me.noticePasswordUpdateFailed);
else
displayMessage(me.noticePasswordUpdated);
}
//}}}
// ccLogin //
//{{{
function isLoggedIn() {
if(window.loggedIn)
return true;
else
return false;
}
config.macros.saveChanges.handler=function(place,macroName,params,wikifier,paramString,tiddler){
if(isLoggedIn()){
createTiddlyButton(place, config.macros.ccLogin.buttonLogout, config.macros.ccLogin.buttonLogoutToolTip, function(){
if (window.fullUrl.indexOf("?") >0)
window.location = window.fullUrl+"&logout=1";
else
window.location = window.fullUrl+"?logout=1";
return false;
},null,null,this.accessKey);
}else{
createTiddlyButton(place,config.macros.ccLogin.buttonlogin, config.macros.ccLogin.buttonLoginToolTip, function() {
story.displayTiddler(null, "Login");
},null,null,this.accessKey);
}
};
if (isLoggedIn()){
config.backstageTasks.push("logout");
merge(config.tasks,{logout:{text: "logout",tooltip: config.macros.ccLogin.buttonLogoutToolTip,content: '<<ccLogin>>'}});
}else{
config.backstageTasks.push("login");
merge(config.tasks,{login:{text: "login",tooltip: config.macros.ccLogin.buttonLoginToolTip,content: '\r\n\r\n<<tiddler Login>>'}});
}
var loginState=null;
var registerState=null;
config.macros.ccLogin.handler=function(place,macroName,params,wikifier,paramString,tiddler){
config.macros.ccLogin.refresh(place);
};
config.macros.ccLogin.refresh=function(place, error){
removeChildren(place);
var w = new Wizard();
if (isLoggedIn()){
w.createWizard(place,this.stepLogoutTitle);
w.addStep(null, this.stepLogoutText+decodeURIComponent(cookieString(document.cookie).txtUserName)+"<br /><br />");
w.setButtons([
{caption: this.buttonLogout, tooltip: this.buttonLogoutToolTip, onClick: function() {window.location=fullUrl+"?&logout=1"}
}]);
return true;
}
w.createWizard(place,this.WizardTitleText);
var me=config.macros.ccLogin;
var oldForm = w.formElem.innerHTML;
var form = w.formElem;
if (error!==undefined)
this.stepLoginTitle=error;
w.addStep(this.stepLoginTitle,me.stepLoginIntroTextHtml);
txtPassword = findRelated(w.formElem.password,"txtPassword","className","previousSibling");
w.formElem.password.style.display="none";
txtPassword.onkeyup = function() {
if(me.sha1 == true)
w.formElem.password.value = Crypto.hexSha1Str(txtPassword.value);
else
w.formElem.password.value = txtPassword.value;
};
txtPassword.onchange = txtPassword.onkeyup;
w.formElem.method ="POST";
w.formElem.onsubmit = function() {config.macros.ccLogin.doLogin(w.formElem["username"].value, w.formElem["password"].value, this, place); return false;};
var submit = createTiddlyElement(null, "input");
submit.type="submit";
submit.style.display="none";
w.formElem.appendChild(submit);
var cookieValues=findToken(document.cookie);
if (cookieValues.txtUserName!==undefined){
w.formElem["username"].value=decodeURIComponent(cookieValues.txtUserName) ;
}
var footer = findRelated(form,"wizardFooter","className");
createTiddlyButton(w.footer,this.buttonLogin,this.buttonLoginToolTip,function() {
if (w.formElem["username"].value==""){
displayMessage(me.msgNoUsername);
return false;
}
if (w.formElem["password"].value==""){
displayMessage(me.msgNoPassword);
return false;
}
config.macros.ccLogin.doLogin(w.formElem["username"].value, w.formElem["password"].value, this, place);
});
var li_register = createTiddlyElement(w.footElem, "label");
createTiddlyButton(w.footElem,this.buttonLogin,this.buttonLoginToolTip,function() {
config.macros.ccLogin.doLogin(w.formElem["username"].value, w.formElem["password"].value, this, place);
},null, null, null, {tabindex:'3'});
if(config.macros.register!==undefined){
var li_register = createTiddlyElement(w.footElem, "li");
createTiddlyButton(li_register,config.macros.register.buttonRegister,config.macros.register.buttonRegisterToolTip,function() {
config.macros.register.displayRegister(place, w, this);
},"nobox", null, null, {tabindex:4});
}
var li_forgotten = createTiddlyElement(w.footElem, "li");
createTiddlyButton(li_forgotten,this.buttonForgottenPassword,this.buttonForgottenPasswordToolTip,function() {
config.macros.ccLogin.displayForgottenPassword(this, place);
},"nobox", null, null, {tabindex:5});
};
config.macros.ccLogin.doLogin=function(username, password, item, place){
var w = new Wizard(item);
var me = config.macros.ccLogin;
var userParams = {};
console.log(config.adaptors);
userParams.place = place;
var adaptor = new config.adaptors[config.defaultCustomFields['server.type']];
var context = {};
context.host = window.url;
context.username = username;
context.password = password;
adaptor.login(context,userParams,config.macros.ccLogin.loginCallback)
var html = me.stepDoLoginIntroText;
w.addStep(me.stepDoLoginTitle,html);
w.setButtons([
{caption: this.buttonCancel, tooltip: this.buttonCancelToolTip, onClick: function() {config.macros.ccLogin.refresh(place);}
}]);
}
config.macros.ccLogin.loginCallback=function(context,userParams){
if(context.status){
window.location.reload();
}else{
config.macros.ccLogin.refresh(userParams.place, config.macros.ccLogin.msgLoginFailed);
}
};
config.macros.ccLogin.displayForgottenPassword=function(item, place){
var w = new Wizard(item);
var me = config.macros.ccLogin;
w.addStep(me.stepForgotPasswordTitle,me.stepForgotPasswordIntroText);
w.setButtons([
{caption: this.buttonCancel, tooltip: this.buttonCancelToolTip, onClick: function() {me.refresh(place);}}
]);
};
//config.macros.ccLogin.sendForgottenPassword=function(item, place){
// var w = new Wizard(item);
// var me = config.macros.ccLogin;
//}
config.macros.toolbar.isCommandEnabled=function(command,tiddler){
var title=tiddler.title;
if (workspace_delete=="D"){
// REMOVE OPTION TO DELETE TIDDLERS
if (command.text=='delete')
return false;
}
if (workspace_udate=="D"){
// REMOVE EDIT LINK FROM TIDDLERS
if (command.text=='edit')
return false;
}
var ro=tiddler.isReadOnly();
var shadow=store.isShadowTiddler(title) && !store.tiddlerExists(title);
return (!ro || (ro && !command.hideReadOnly)) && !(shadow && command.hideShadow);
};
// Returns output var with output.txtUsername and output.sessionToken
function findToken(cookieStash){
var output={};
if (!cookieStash)
return false;
// THIS IS VERY HACKY AND SHOULD BE REFACTORED WHEN TESTS ARE IN PLACE
var cookies=cookieStash.split('path=/');
for(var c=0; c < cookies.length ; c++){
var cl =cookies[c].split(";");
for(var e=0; e < cl.length; e++){
var p=cl[e].indexOf("=");
if(p!=-1){
var name=cl[e].substr(0,p).trim();
var value=cl[e].substr(p+1).trim();
if (name=='txtUserName'){
output.txtUserName=value;
}
if (name=='sessionToken'){
output.sessionToken=value;
}
}
}
}
return output;
};
function cookieString(str){
var cookies = str.split(";");
var output = {};
for(var c=0; c < cookies.length; c++){
var p = cookies[c].indexOf("=");
if(p != -1) {
var name = cookies[c].substr(0,p).trim();
var value = cookies[c].substr(p+1).trim();
if (name=='txtUserName'){
output.txtUserName=value;
}
if (name=='sessionToken'){
output.sessionToken=value;
}
}
}
return output;
}
Story.prototype.displayDefaultTiddlers = function(){
var tiddlers="";
if(isLoggedIn()){
var url = window.location;
url = url.toString();
var bits = url.split('#');
if(bits.length == 1){
tiddlers = store.filterTiddlers(store.getTiddlerText("DefaultTiddlers"));
story.displayTiddlers(null, tiddlers);
}
}else{
tiddlers=store.filterTiddlers(store.getTiddlerText("AnonDefaultTiddlers"));
story.displayTiddlers(null, tiddlers);
}
};
window.restart = function(){
story.displayDefaultTiddlers();
invokeParamifier(params,"onstart");
window.scrollTo(0,0);
};
//}}}
// ccLoginStatus //
//{{{
config.macros.ccLoginStatus.handler=function(place,macroName,params,wikifier,paramString,tiddler){
var loginDiv=createTiddlyElement(place,"div",null,"loginDiv",null);
this.refresh(loginDiv);
};
config.macros.ccLoginStatus.refresh=function(place,errorMsg){
var me = config.macros.ccLoginStatus;
var loginDivRef=document.getElementById ("LoginDiv");
removeChildren(loginDivRef);
var wrapper=createTiddlyElement(place,"div");
var str = (workspace == "" ? me.textDefaultWorkspaceLoggedIn :(me.textViewingWorkspace+workspace))+"\r\n\r\n";
if (isLoggedIn()){
name = cookieString(document.cookie).txtUserName;
str += me.textLoggedInAs+decodeURIComponent(name)+".\r\n\r\n";
if (workspacePermission.owner==1){
str += me.textAdmin;
}
}else{
str += me.textNotLoggedIn;
}
wikify(str,wrapper);
};
//}}}
// ccOptions //
//{{{
config.macros.ccOptions.handler=function(place,macroName,params,wikifier,paramString,tiddler){
var me = config.macros.ccOptions;
if(workspacePermission.owner==1)
wikify("[["+me.linkManageUsers+"|Manage Users]]<br />[["+me.linkPermissions+"|Permissions]]<br />[["+me.linkStats+"|Statistics]]<br />", place);
if (isLoggedIn())
wikify("[["+me.linkFiles+"|files]]<br />", place);
if (isLoggedIn()){
if (workspacePermission.canCreateWorkspace==1)
wikify("[["+me.linkCreate+"|CreateWorkspace]]<br />", place);
// append url function required
wikify("[["+me.linkPassword+"|Password]]<br />", place);
if (window.fullUrl.indexOf("?") >0)
wikify("[["+me.linkOffline+"|"+fullUrl+"&standalone=1]]<br />", place);
else
wikify("[["+me.linkOffline+"|"+fullUrl+"?standalone=1]]<br />", place);
}
};
//}}}
// ccRegister //
//{{{
config.macros.register.handler=function(place,macroName,params,wikifier,paramString,tiddler){
//config.macros.login.refresh(place);
};
config.macros.register.displayRegister=function(place, w, item){
var me = config.macros.register;
var w = new Wizard(item);
w.addStep(me.stepRegisterTitle, me.stepRegisterHtml);
w.formElem["reg_username"].onkeyup=function() {me.isUsernameAvailable(w);};
w.setButtons([
{caption: me.buttonRegister, tooltip: me.buttonRegisterToolTip, onClick:function() { me.doRegister(place, w)}},
{caption: me.buttonCancel, tooltip: me.buttonCancelToolTip, onClick: function() { config.macros.ccLogin.refresh(place)}}
]);
var h1 = createTiddlyElement(null, "h1", null, null, "hahahaha");
// w.footElem.appendChild(h1, w.footElem);
w.footElem.firstChild.parentNode.appendChild(h1, w.footElem);
//w.footElem.firstChild.insertBefore(h1, w.footElem);
}
config.macros.register.setStatus=function(w, element, text){
var label_var = w.getElement(element);
removeChildren(label_var.previousSibling);
var label = document.createTextNode(text);
label_var.previousSibling.insertBefore(label,null);
}
config.macros.register.doRegister=function(place, w){
var me = config.macros.register;
if(w.formElem["reg_username"].value==''){
me.setStatus(w, "username_error", me.msgNoUsername);
}else {
me.setStatus(w, "username_error", "");
}
if(me.emailValid(w.formElem["reg_mail"].value)){
me.setStatus(w, "mail_error", me.msgEmailOk);
}else{
me.setStatus(w, "mail_error", "invalid email address");
return false;
}
if(w.formElem["reg_password1"].value==''){
me.setStatus(w, "pass1_error", me.msgNoPassword);
return false;
}else{
me.setStatus(w, "pass1_error", "");
}
if(w.formElem["reg_password2"].value==''){
me.setStatus(w, "pass2_error", me.msgNoPassword);
return false;
}
if(w.formElem["reg_password1"].value != w.formElem["reg_password2"].value ){
me.setStatus(w, "pass1_error", me.msgDifferentPasswords);
me.setStatus(w, "pass2_error", me.msgDifferentPasswords);
return false;
}
var params ={};
params.p = Crypto.hexSha1Str(w.formElem['reg_password1'].value);
params.u = w.formElem['reg_username'].value;
params.place = place;
params.w = w;
var loginResp=doHttp('POST',url+'/handle/register.php',"username="+w.formElem['reg_username'].value+"®_mail="+w.formElem['reg_mail'].value+"&password="+Crypto.hexSha1Str(w.formElem['reg_password1'].value)+"&password2="+Crypto.hexSha1Str(w.formElem['reg_password2'].value),null,null,null,config.macros.register.registerCallback,params);
w.addStep(me.step2Title, me.msgCreatingAccount);
w.setButtons([
{caption: me.buttonCancel, tooltip: me.buttonCancelToolTip, onClick: function() {config.macros.ccLogin.refresh(place);}
}]);
}
config.macros.register.emailValid=function(str){
if((str.indexOf(".") > 0) && (str.indexOf("@") > 0))
return true;
else
return false;
};
config.macros.register.usernameValid=function(str){
if((str.indexOf("_") > 0) && (str.indexOf("@") > 0))
return false;
else
return true;
};
config.macros.register.registerCallback=function(status,params,responseText,uri,xhr){
var userParams = {};
userParams.place = params.place;
if (xhr.status==304){
params.w.addStep(config.macros.register.errorRegisterTitle, config.macros.register.errorRegister);
return false;
}
var adaptor = new config.adaptors[config.defaultCustomFields['server.type']];
var context = {};
context.host = window.url;
context.username = params.u;
context.password = params.p;
adaptor.login(context,userParams,config.macros.ccLogin.loginCallback);
return true;
}
config.macros.register.isUsernameAvailable=function(w){
var params = {};
params.w = w;
doHttp('POST',url+'/handle/register.php',"username="+w.formElem["reg_username"].value+"&free=1",null,null,null,config.macros.register.isUsernameAvailabeCallback,params);
return false;
};
config.macros.register.isUsernameAvailabeCallback=function(status,params,responseText,uri,xhr){
var me = config.macros.register;
var resp = (responseText > 0) ? me.msgUsernameTaken : me.msgUsernameAvailable;
config.macros.register.setStatus(params.w, "username_error", resp);
};
//}}}
// ccStats //
//{{{
config.macros.ccStats.handler = function(place,macroName,params,wikifier,paramString,tiddler){
var params;
params.place = place;
doHttp('POST',url+'/handle/workspaceAdmin.php','action=LISTWORKSPACES',null,null,null,config.macros.ccStats.listWorkspaces,params);
}
config.macros.ccStats.simpleEncode = function(valueArray,maxValue){
var simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var chartData = ['s:'];
for (var i = 0; i < valueArray.length; i++){
var currentValue = valueArray[i];
if (!isNaN(currentValue) && currentValue >= 0){
chartData.push(simpleEncoding.charAt(Math.round((simpleEncoding.length-1) * currentValue / maxValue)));
}else{
chartData.push('_');
}
}
return chartData.join('');
}
config.macros.ccStats.max = function(array){
return Math.max.apply(Math, array);
}
config.macros.ccStats.dataCallback = function(status,params,responseText,uri,xhr){
me = config.macros.ccStats;
if(xhr.status==401){
createTiddlyElement(params.container, "h4", null, null, me.errorPermissionDenied.format([params.title], [workspace]));
return false;
}
var res = eval("[" + responseText + "]");
var d=[];
var l="";
for(var c=0; c<res.length; c++){
d[c]= res[c].hits;
l+=res[c].date+"|";
}
var maxValue = config.macros.ccStats.max(d);
params.gData = config.macros.ccStats.simpleEncode(d,maxValue);
params.XLabel = l.substring(0, l.length -1);
params.YLabel = "0|"+maxValue+"|";
var image = 'http://chart.apis.google.com/chart?cht=lc&chs=100x75&chd='+params.gData+'&chxt=x,y&chxl=0:||1:|';
var div = createTiddlyElement(params.container, "div", null, "div_button");
setStylesheet(".div_button:hover{opacity:0.7; cursor: pointer} .div_button{ width:100%; padding:5px;color:#555;background-color:white;} ", "DivButton");
div.onclick = function(){
var full = "http://chart.apis.google.com/chart?cht=lc&chs=800x375&chd="+params.gData+"&chxt=x,y&chxl=1:|"+params.YLabel+"0:|"+params.XLabel+"&chf=c,lg,90,EEEEEE,0.5,ffffff,20|bg,s,FFFFFF&&chg=10.0,10.0&";
setStylesheet(
"#errorBox .button{padding:0.5em 1em; border:1px solid #222; background-color:#ccc; color:black; margin-right:1em;}\n"+
"html > body > #backstageCloak{height:"+window.innerHeight*2+"px;}"+
"#errorBox{border:1px solid #ccc;background-color: #fff; color:#111;padding:1em 2em; z-index:9999;}",'errorBoxStyles');
var box = document.getElementById('errorBox') || createTiddlyElement(document.body,'div','errorBox');
box.innerHTML = "<a style='float:right' href='javascript:onclick=ccTiddlyAdaptor.hideError()'>"+ccTiddlyAdaptor.errorClose+"</a><h3>"+params.title+"</h3><br />";
box.style.position = 'absolute';
box.style.height= "460px";
box.style.width= "800px";
var img = createTiddlyElement(box, "img");
img.src = full;
ccTiddlyAdaptor.center(box);
ccTiddlyAdaptor.showCloak();
}
var img = createTiddlyElement(div, "h2", null, null, params.title);
var img = createTiddlyElement(div, "img");
img.src = image;
var span = createTiddlyElement(div, "div", null, "graph_label", params.desc);
setStylesheet(".graph_label{ position:relative; width:300px; top:-80px; left:130px;}");
}
config.macros.ccStats.switchWorkspace = function(params){
removeChildren(params.container);
config.macros.ccStats.refresh(params);
}
config.macros.ccStats.refresh = function(params){
var me = config.macros.ccStats;
var select = params.w.formElem.workspaces;
if(select[select.selectedIndex].value!="")
workspace = select[select.selectedIndex].value;
params ={ container: params.container, url: window.url+"/handle/stats.php?graph=minute&workspace="+workspace,title:me.graph20MinsTitle, desc:me.graph20MinsDesc};
doHttp('GET',params.url,null, null, null, null, config.macros.ccStats.dataCallback,params);
params ={ container:params.container, url: window.url+"/handle/stats.php?graph=hour&workspace="+workspace,title:me.graph24HourTitle, desc:me.graph24HourDesc};
doHttp('GET',params.url,null, null, null, null, config.macros.ccStats.dataCallback,params);
params ={ container: params.container, url: window.url+"/handle/stats.php?graph=day&workspace="+workspace,title:me.graph7DaysTitle, desc:me.graph7DaysDesc};
doHttp('GET',params.url,null, null, null, null, config.macros.ccStats.dataCallback,params);
params ={ container: params.container, url: window.url+"/handle/stats.php?graph=month&workspace="+workspace,title:me.graph5MonthsTitle, desc:me.graph5MonthsDesc};
doHttp('GET',params.url,null, null, null, null, config.macros.ccStats.dataCallback,params);
}
config.macros.ccStats.listWorkspaces = function(status,params,responseText,uri,xhr){
params.container=createTiddlyElement(null, "div", "container");
var me = config.macros.ccStats;
var w = new Wizard();
w.createWizard(params.place,me.stepTitle);
w.addStep(null, "<select name='workspaces'></select><input name='stats_hol' type='hidden'></input>");
var s = w.formElem.workspaces;
s.onchange = function(){config.macros.ccStats.switchWorkspace(params) ;};
var workspaces = eval('[ '+responseText+' ]');
for(var d=0; d < workspaces.length; d++){
var i = createTiddlyElement(s,"option",null,null,workspaces[d]);
i.value = workspaces[d];
if (workspace == workspaces[d]){
i.selected = true;
}
}
params.w = w;
w.formElem.stats_hol.parentNode.appendChild(params.container);
config.macros.ccStats.refresh(params);
}
//}}}
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.4.1|
|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|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.''
!!!!!Documentation
>see [[TaggedTemplateTweakInfo]]
!!!!!Revisions
<<<
2008.08.29 [1.4.1] corrected handling for tiddlers with no matching tagged template when non-default theme is in effect (e.g., use "MyTheme##ViewTemplate").
| please see [[TaggedTemplateTweakInfo]] for previous revision details |
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TaggedTemplateTweak= {major: 1, minor: 4, revision: 1, date: new Date(2008,8,29)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
// get default template from core
var coreTemplate=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
// if the tiddler doesn't exist yet or is untagged, return core result
var tiddler=store.getTiddler(title);
if (!tiddler || !tiddler.tags.length)
return coreTemplate;
// split core template into theme prefix and template name
var theme="";
var template=coreTemplate;
var parts=template.split(config.textPrimitives.sectionSeparator);
if (parts[1]) { theme=parts[0]; template=parts[1]; }
else theme=config.options.txtTheme||""; // fallback if theme is not specified
theme+=config.textPrimitives.sectionSeparator;
// look for template whose prefix matches a tag on this tiddler (if any)
for (i=0; i<tiddler.tags.length; i++) {
var t=tiddler.tags[i]+template; // add tag prefix to template
var c=t.substr(0,1).toUpperCase()+t.substr(1); // capitalized for WikiWord title
if (store.getTiddlerText(theme+t)) { return theme+t; } // theme##tagTemplate
if (store.getTiddlerText(theme+c)) { return theme+c; } // theme##TagTemplate
if (store.getTiddlerText(t)) { return t; } // tagTemplate
if (store.getTiddlerText(c)) { return c; } // TagTemplate
}
return coreTemplate; // no matching tag, return core result
}
More info on the company (~OsmoSoftians!!) and its products can be found one the [[osmosoft.com homepage|http://osmosoft.com/]]
If you don't already have an account here please [[register|Register]] for one. (Note that user registration is a new feature and still requires some work.)
If you have any problems with this deployment please contact simon@osmosoft.com.
Feedback is welcomed!
when creating a link using ''[''''['', it may open a new window depending on its settings. One can now override this behaviour by using a ''~'' at the begining of the link like
[[a link to google|~http://google.com]]
NB: this isn't working
Well, with help from a number of sources I've nailed the basics ... even discovered how to do --strikeout--!
----
--see [[Requirements]] from http://cctiddly.sourceforge.net/-- ... this didn't work. Dunno why, copied the source directly from the original. ''This is now working''
AltMenu is the Main Menu from http://www.hawksworx.com/playground/TeamTasks/ ... a simple slider, without the nice internal nesting the other has, but at least this works here.
!!!Requirements
ccTiddly can be hosted using the following environment (click on the link to see details)
#+++^[Public free web server]<<tiddler "Public free web server">>===
#+++^[Rent some webspace from web providers]<<tiddler "Rent some webspace from web providers">>===
#+++^[Setup your own server]<<tiddler "Setup your own server">>===
After picking your server environment, you can proceed to install.
<<tag requirements>>
It's about discourse! (Provided by [[Osmosoft]] using [[ccTiddlyWiki]].)
This is paradigmatically different in many, many ways. 1st, no evidence of markup ... or help on the subject. 2nd failure at an intuitive level e.g. I add an item to DefaultTiddlers but don't see how I can add that to the menu alongside GettingStarted. 3rd, just plain weirdness: "Help" is located under "Options" ... HeyHo.
bummer
[[12 July 2008]]
[[10 July 2008]]
OpenSourceCommunity
MoralProvocation
"''Even if you don't care, it still matters!''"
If there's something you don't care about, that "something" may still matter, it may be quite important.
If there's something that's important that you don't care about, the fact that you don't care about it may be important! You not caring may matter a lot.
Living as though we're contented cows is no way to live ... we're human beings, we're sentient. When we don't respond to moral provocation it's exactly as though we'd been lobotomized.
for more see http://groundplane.wordpress.com/gp-101/
Since "New Journal" doesn't create a CamelCase tiddler, I wasn't able to add that item to DefaultTiddlers. So I created this one. Which doesn't show up as a link in DefaultTiddlers. *sigh*
This is paradigmatically different in many, many ways. 1st, no evidence of markup ... or help on the subject. 2nd failure at an intuitive level e.g. I add an item to DefaultTiddlers but don't see how I can add that to the menu alongside GettingStarted. 3rd, just plain weirdness: "Help" is located under "Options" ... HeyHo.
bummer
* ChrisDentSez
**ChrisDentSez1
**ChrisDentSez2
<<dropMenu vertical>>
----
* Blurts
** [[4th Estate 5th Column?|Is the Fourth Estate a Fifth Column?]]
** CordonBlue
** [[w/Chris Brogan|ChrisBrogan1]]
** [[OS & Community|OpenSourceCommunity]]
** MoralProvocation
* Journals
** [[12July08|12 July 2008]]
** [[10July08|10 July 2008]]
** [[3July08|3 July 2008]]
** [[29June08|29 June 2008]]
** [[28June08|28 June 2008]]
** [[27June08|27 June 2008]]
** [[26June08-2|26 June 2008-2]]
** [[26June08|26 June 2008]]
** [[25June08|25 June 2008]]
** [[23June08-2]]
** [[23June08]]
<<dropMenu vertical>>
----
* [[Customization]]
* GettingStarted
* [[Resources|Resources]]
<<dropMenu vertical>>
----
----
*AboutMe
*[[Comment!|GFreeComment]]
<<dropMenu vertical>>
<<tiddler LeftSideFooter>>
[[Blurts]] | [[Journals]] | MainMenu |
DefaultTiddlers | AnonDefaultTiddlers | SiteTitle & SiteSubtitle |
<<ccEditWorkspace>> allows users update the permissions of a workspace after it has
been created
And <<ccAdmin>> allows users to add/remove admin users from workspaces for which
they themselves are an administrator.
*PageTemplate -- Contains the overall structure of the page, including the gradient macro for the masthead.
*EditTemplate -- Contains the structure and order of the tiddler editor screen
*ViewTemplate -- Contains the structure and order of the tiddler view screen
*ToolbarCommands | SideBarTabs
*StyleSheetColors -- Contains the CSS for colors
*StyleSheetLayout -- Contains the CSS for layout
*StyleSheetPrint -- Contains the CSS used when printing from the TiddlyWiki
----
The following block was ripped off from [[the tiddlywiki homepage|http://tiddlywiki.com/]]
----
You can customise the appearance and behaviour of TiddlyWiki to almost any degree you want:
* Use the ColorPalette to change the basic colour scheme
* Create a CustomStyleSheet for finer grained control over the appearance
* Customise the PageTemplate, ViewTemplate or EditTemplate to change the composition of the page and the layout of individual tiddlers
* Use off-the-shelf themes from [[TiddlyThemes|http://tiddlythemes.com/]]
* Visit the [[Configuration]] summary to see all the special configuration tiddlers
* Install [[Plugins]] to extend the core functionality (find them at [[TiddlyVault|http://tiddlyvault.tiddlyspot.com/]] or you can try [[writing or adapting your own|http://gimcrackd.com/etc/src/codex/]])
* Use TiddlyBookmarklets for low level hacking of TiddlyWiki documents
There are also a bunch of TiddlyWikiTools that you can use to enhance TiddlyWiki.
----
<<slider chkSliderOptionsPanel Resources 'Resources »' 'A list of sites'>>
<<tag resources>>
You can also get free webspace from some public servers out there (such as [[byethost|http://byethost.com/]] and [[lycos (tripod)|http://www.tripod.lycos.co.uk/]]. Whichever providers you choose, you will need:
*~PHP4/5
*~MySQL
''Benefit''
*Free (as in beer)
*Uptime (depending on your provider, but usually not as good as paid hosting)
*Saves time from maintaining server
''Issues''
*Advertising on your page
*Database is "not as private" since your provider now have access to it
Here is a ''step-by-step'' installation tutorial for [[Byethost|Installing on byethost]] and [[Lycos|Installing on lycos]]
(//recent first//)
- [[10JULY08|10 July 2008]]
- [[3JULY08|3 July 2008]]
- [[29June08|29 June 2008]]
- [[28June08|28 June 2008]]
- [[27June08|27 June 2008]]
- [[26June08-2|26 June 2008-2]]
- [[26June08|26 June 2008]]
- [[25June08|25 June 2008]]
- [[23June08-2]]
- [[23June08]]
<<slider chkSliderOptionsPanel Items 'Items »' 'A second list of journals'>>
<<tag menus>>
- [[Blank1]]
- [[Blank2]]
see irc://irc.freenode.net/tiddlywiki
<<slider chkSliderOptionsPanel ccTWRes 'ccTiddly »' 'A list of sites'>>
<<slider chkSliderOptionsPanel TWRes 'TIddlyWiki »' 'A list of sites'>>
<<slider chkSliderOptionsPanel RRapRes 'RippleRap »' 'A list of sites'>>
[[TWRes]] [[ccTWRes]] [[RRapRes]]
----
<<slider chkSliderOptionsPanel GettingStarted 'Getting Started »' 'A list of sites'>>
<<tag resources>>
Originally posted as [[a comment to Nick Webb's "Tiddlypreneurship at Osmosoft"|http://www.erraticmusings.com/?p=16]]:
As for “whether or not open source software is solely the domain of developers” I’d agree with you on “shouldn’t be”, but would quite confidantly say “Is, most of the time, very definitely.”
Take ccTW for example. I got [[mine up and running at osmosoft|http://wiki.osmosoft.com/alpha/pardelib]] pretty quickly after having come across [[Confabb’s “Note Saver"|http://blog.confabb.com/?p=106]]. Fast start followed by grinding frustration … for example markup copied from another TW not working on my install; not the sort of snafu you want to encounter on your first day.
Addressing documentation (my trade) it’s only natural that developers leave just enough cookie crumbs for others like them to find their work … which isn’t at all the same as enabling a naive participant.
Case in point: configuration of a server side install. I’ve found a lot of Tiddlers that nominally address that, but none of them have actual config data and instructions.
Oh-wooops, one of them does … incidentally … the one that describes installing at Lycos. Go figure!
It’s a cultural thing. Developers leave gaping voids where they (quite correctly) presume other developers to be up to speed. In my estimation encountering 2 or 3 of those voids would be enough to deter a naive participant … and nobody would ever know.
It’s a cultural thing.
Ben Tremblay at June 24th, 2008 around 6:10 pm
----
''Update //14:35MDT 30JUNE08//''
From my experience with ~OpenSource settings (most recently [[TiddlyIRC|irc://irc.freenode.net/tiddlywiki]]) these are (in contradistinction to the paradigmatic hippie-bus setting, or the best of garage startups), somewhat like NGOs and not.for.profit situations (which are gardens of personality games and opportunistic nastiness), these situations are hallmarked by individuals who score points by the quality of their passive aggression and its attendant plausible deniability i.e. diss and ignore are the most used tools.
----
|''Type:''|file|
|''URL:''|http://cctiddly.sourceforge.net/|
|''Workspace:''|(default)|
This tiddler was automatically created to record the details of this server
!!~TiddlyWiki Resources
*[[Main TiddlyWiki site|http://www.tiddlywiki.com]] and [[Developers' site|http://www.tiddlywiki.org/wiki/TiddlyWeb]]
*[[TWFaq at TiddlySpot|http://twfaq.tiddlyspot.com/]]
*[[Julian Knight's references|http://knighjm.googlepages.com/knightnet-default-tw.html]]
*[[Google Group|http://groups.google.com/group/TiddlyWiki]]
*[[Developers Google Group|http://groups.google.com/group/TiddlyWikiDev]]
*[[Write-up at OsmoSoft|http://osmosoft.com/#TiddlyWiki]]
{{comments{
{{comment{
!2008-07-11 01:54 UTC
!!BenTrem
Will this tiddler now be lofted to the top of timeline?
}}}
}}}
A reply I just crafted while chatting with [[Chris Brogan|http://twitter.com/chrisbrogan]] on ~FaceBook:
""We're tying threads together."
Indeed, indeed!
Have you come across "autopoesis"?
Fractals and such ... self-organizing systems ...
So long as a critical number of individuals are striving towards ?what? however they conceive of "the good", things will work themselves out. Kinda like how in conflict situations (Gaza, Iraq, Sudan) all that's required for evil to triumph is that people of good-will do nothing.
Michael Mandelbaum was on Charlie Rose last night ... produced a nice trope: "the irresistable force of democracy and free markets meeting the immovable object that is China's Communist Party" ... it's like that ... tectonic.
My worry: that "fun" increase dissipation catastrophically. (~MySpace comes to mind.)
My project: to create an online system that empowers real discourse. (For my money, conventional forums / wiki / blogs don't cut the mustard.)
!!ccTiddly Resources
[[ccTiddly at TiddlyWiki.org|http://tiddlywiki.org/wiki/CcTiddly]] and [[Sourceforge Homepage|http://cctiddly.sourceforge.net/]] (see [[Requirements]])
[[ccTiddly hosting at OsmoSoft|http://wiki.osmosoft.com/alpha]]
[[Google user group|http://groups.google.com/group/ccTiddly]]
[[SourceForge Forum|http://sourceforge.net/forum/forum.php?forum_id=523746]]
Blogs: [[Simon's blog|http://wordpress.com/tag/cctiddly/]] and [[Matthew |http://coolcold.wordpress.com/category/cctiddly/]].
!!~RippleRap Resources
[[HomePage|http://www.ripplerap.com/]]
[[Write-up at OsmoSoft|http://osmosoft.com/#RippleRap]]
I just now discovered AnonDefaultTiddlers ... a good thing to find!
A few minutes ago I finished the first cut of [[Resources]] ... something to build on.
Earlier, with email from Simon, I gave Import a spin ... managed to grab one Tiddler, but --didn't get the slider functionality I'd wanted. ~HeyHo, and so it goes!--
//Addendum//: ~Ace_NoOne on IRC pointed me to this: [[SourceForge #NestedSlidersPlugin|http://cctiddly.sourceforge.net/#NestedSlidersPlugin]]
That brought me to [[TiddlyTools #NestedSlidersPlugin|http://www.tiddlytools.com/#NestedSlidersPlugin]] and [[TiddlyTools #NestedSlidersPluginInfo|http://www.tiddlytools.com/#NestedSlidersPluginInfo]]
The key instructions were on [[the Wiki Plugins page|http://www.tiddlywiki.org/wiki/Plugins]], i.e. "In order to install a plugin, the respective tiddler(s) need to be imported (or simply copied in edit mode) from the source into the TiddlyWiki document. In order to be processed on startup, plugins need to be assigned the "systemConfig" tag. "
[[Requirements]] is now fully nested.
>//NB: constantly having to log in again and again and again is fucking bullshit. Ok? Ok. Now, where was I ... ohhhh yaa, now I have to restore that whole fucking paragraph full of links. (How long has this been around? Yaa yaa I know, all I'm good for is picking gnits ... GD amateurs.)
It's like Twitter ... unless you want to lose your work before committing you select all and copy, then hit the button.//
----
Of historical interest:
*A [[whole list of interviews with TiddlyHackers|http://mptw1.tiddlyspot.com/#The TiddlyWiki Report]] at Simon Baird's [["MonkeyPirateTiddlyWiki"|http://mptw1.tiddlyspot.com/]]. (Do peek [[Simon's main blog|http://glosoli.blogspot.com/]].)
Case in point: [["The TiddlyWiki Report, Part IV: Jeremy Ruston"|http://loosewire.typepad.com/blog/2005/08/the_tiddlywiki__3.html]] ("The man who started it all".)
AnonGreets
[[29 June 2008]]
OpenSourceCommunity
MoralProvocation
Hi! You've found your way to my (very preliminary) ~ParDelib page.
I invite you to snoop the material in the MainMenu ...
... but perhaps you want to set up your own ccTiddlyWiki? (That's the software this site is running.)
If that's the case, then head on over to [[OsmoSoft's hosting site|http://wiki.osmosoft.com/alpha/]] ... fill your boots!
- -[[bentrem|http://twitter.com/bentrem]]
* Login
**{{myclass{
<<ccLogin>>
}}}
* Comment!
**{{myclass{
<<tiddler [[GFreeComment]]>>
}}}
* Register Your Workspace
**{{myclass{
<<ccRegister>>
}}}
<<accordion>>
<<ccLoginStatus>>
|''Type:''|file|
|''URL:''|http://cctiddly.sourceforge.net|
|''Workspace:''|(default)|
This tiddler was automatically created to record the details of this server
/***
''NestedSlidersPlugin for TiddlyWiki version 1.2.x and 2.0''
^^author: Eric Shulman
source: http://www.TiddlyTools.com/#NestedSlidersPlugin
license: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^
Quickly make any tiddler content into an expandable 'slider' panel, without needing to create a separate tiddler to contain the slider content. Optional syntax allows ''default to open'', ''custom button label/tooltip'' and ''automatic blockquote formatting.''
You can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created. This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.
For more details, please click on a section headline below:
++++!!!!![Configuration]>
Debugging messages for 'lazy sliders' deferred rendering:
<<option chkDebugLazySliderDefer>> show debugging alert when deferring slider rendering
<<option chkDebugLazySliderRender>> show debugging alert when deferred slider is actually rendered
===
++++!!!!![Usage]>
When installed, this plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content. Use {{{+++}}} and {{{===}}} to delimit the slider content. Additional optional syntax elements let you specify
*default to open
*cookiename
*heading level
*floater (with optional CSS width value)
*mouse auto rollover
*custom class/label/tooltip/accesskey
*automatic blockquote
*deferred rendering
The complete syntax, using all options, is:
//{{{
++++(cookiename)!!!!!^width^*{{class{[label=key|tooltip]}}}>...
content goes here
===
//}}}
where:
* {{{+++}}} (or {{{++++}}}) and {{{===}}}^^
marks the start and end of the slider definition, respectively. When the extra {{{+}}} is used, the slider will be open when initially displayed.^^
* {{{(cookiename)}}}^^
saves the slider opened/closed state, and restores this state whenever the slider is re-rendered.^^
* {{{!}}} through {{{!!!!!}}}^^
displays the slider label using a formatted headline (Hn) style instead of a button/link style^^
* {{{^width^}}} (or just {{{^}}})^^
makes the slider 'float' on top of other content rather than shifting that content downward. 'width' must be a valid CSS value (e.g., "30em", "180px", "50%", etc.). If omitted, the default width is "auto" (i.e., fit to content)^^
* {{{*}}}^^
automatically opens/closes slider on "rollover" as well as when clicked^^
* {{{{{class{[label=key|tooltip]}}}}}}^^
uses custom label/tooltip/accesskey. {{{{{class{...}}}}}}, {{{=key}}} and {{{|tooltip}}} are optional. 'class' is any valid CSS class name, used to style the slider label text. 'key' must be a ''single letter only''. Default labels/tootips are: ">" (more) and "<" (less), with no default access key assignment.^^
* {{{">"}}} //(without the quotes)//^^
automatically adds blockquote formatting to slider content^^
* {{{"..."}}} //(without the quotes)//^^
defers rendering of closed sliders until the first time they are opened. //Note: deferred rendering may produce unexpected results in some cases. Use with care.//^^
//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//
===
++++!!!!![Examples]>
simple in-line slider:
{{{
+++
content
===
}}}
+++
content
===
----
use a custom label and tooltip:
{{{
+++[label|tooltip]
content
===
}}}
+++[label|tooltip]
content
===
----
content automatically blockquoted:
{{{
+++>
content
===
}}}
+++>
content
===
----
all options combined //(default open, cookie, heading, sized floater, rollover, class, label/tooltip/key, blockquoted, deferred)//
{{{
++++(testcookie)!!!^30em^*{{big{[label=Z|click or press Alt-Z to open]}}}>...
content
===
}}}
++++(testcookie)!!!^30em^*{{big{[label=Z|click or press Alt-Z to open]}}}>...
content
===
----
complex nesting example:
{{{
+++^[get info...=I|click for information or press Alt-I]
put some general information here, plus a floating slider with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===
===
===
}}}
+++^[get info...=I|click for information or press Alt-I]
put some general information here, plus a floating slider with more specific info:
+++^10em^[view details...|click for details]
put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===
===
===
===
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''NestedSlidersPlugin'' (tagged with <<tag systemConfig>>)
<<<
!!!!!Revision History
<<<
''2006.07.28 - 2.0.0'' added custom class syntax around label/tip/key syntax: {{{{{classname{[label=key|tip]}}}}}}
''2006.07.25 - 1.9.3'' when parsing slider, save default open/closed state in button element, then in onClickNestedSlider(), if slider state matches saved default, instead of saving cookie, delete it. Significantly reduces the 'cookie overhead' when default slider states are used.
''2006.06.29 - 1.9.2'' in onClickNestedSlider(), when setting focus to first control, skip over type="hidden"
''2006.06.22 - 1.9.1'' added panel.defaultPanelWidth to save requested panel width, even after resizing has changed the style value
''2006.05.11 - 1.9.0'' added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label
''2006.05.09 - 1.8.0'' in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element
''2006.04.24 - 1.7.8'' in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position
''2006.02.16 - 1.7.7'' corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie
''2006.02.15 - 1.7.6'' in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)
''2006.02.04 - 1.7.5'' add 'var' to unintended global variable declarations to avoid FireFox 1.5.0.1 crash bug when assigning to globals
''2006.01.18 - 1.7.4'' only define adjustSliderPos() function if it has not already been provided by another plugin. This lets other plugins 'hijack' the function even when they are loaded first.
''2006.01.16 - 1.7.3'' added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels. While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels. Short-term workaround is to only adjust the position for 'top-level' floaters.
''2006.01.16 - 1.7.2'' added button property to slider panel elements so that slider panel can tell which button it belongs to. Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
''2006.01.14 - 1.7.1'' added optional "^" syntax for floating panels. Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.
''2006.01.14 - 1.7.0'' added optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)
''2006.01.03 - 1.6.2'' When using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element. (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)
''2005.12.15 - 1.6.1'' added optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders
removed checkbox option for 'global' application of lazy sliders
''2005.11.25 - 1.6.0'' added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)
''2005.11.21 - 1.5.1'' revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability. Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.
''2005.11.20 - 1.5.0'' added (cookiename) syntax for optional tracking and restoring of slider open/close state
''2005.11.11 - 1.4.0'' added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style
''2005.11.07 - 1.3.0'' removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other
formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines
''2005.11.05 - 1.2.1'' changed name to NestedSlidersPlugin
more documentation
''2005.11.04 - 1.2.0'' added alternative character-mode syntax {{{(((}}} and {{{)))}}}
tweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax
''2005.11.03 - 1.1.1'' fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used
code cleanup, added documentation
''2005.11.03 - 1.1.0'' changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}
changed name to EasySlidersPlugin
''2005.11.03 - 1.0.0'' initial public release
<<<
!!!!!Credits
<<<
This feature was implemented by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]] with initial research and suggestions from RodneyGomes, GeoffSlocock, and PaulPetterson.
<<<
!!!!!Code
***/
//{{{
version.extensions.nestedSliders = {major: 2, minor: 0, revision: 0, date: new Date(2006,7,28)};
//}}}
//{{{
// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkDebugLazySliderDefer==undefined) config.options.chkDebugLazySliderDefer=false;
if (config.options.chkDebugLazySliderRender==undefined) config.options.chkDebugLazySliderRender=false;
// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");
//}}}
//{{{
config.formatters.push( {
name: "nestedSliders",
match: "\\n?\\+{3}",
terminator: "\\s*\\={3}\\n?",
lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\[\\>]*\\^)?)?(\\*)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(?:\\}{3})?(\\>)?(\\.\\.\\.)?\\s*",
handler: function(w)
{
// defopen=lookaheadMatch[1]
// cookiename=lookaheadMatch[2]
// header=lookaheadMatch[3]
// panelwidth=lookaheadMatch[4]
// rollover=lookaheadMatch[5]
// class=lookaheadMatch[6]
// label=lookaheadMatch[7]
// blockquote=lookaheadMatch[8]
// deferred=lookaheadMatch[9]
lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
{
// location for rendering button and panel
var place=w.output;
// default to closed, no cookie, no accesskey
var show="none"; var title=">"; var tooltip="show"; var cookie=""; var key="";
// extra "+", default to open
if (lookaheadMatch[1])
{ show="block"; title="<"; tooltip="hide"; }
// cookie, use saved open/closed state
if (lookaheadMatch[2]) {
cookie=lookaheadMatch[2].trim().slice(1,-1);
cookie="chkSlider"+cookie;
if (config.options[cookie]==undefined)
{ config.options[cookie] = (show=="block") }
if (config.options[cookie])
{ show="block"; title="<"; tooltip="hide"; }
else
{ show="none"; title=">"; tooltip="show"; }
}
// parse custom label/tooltip/accesskey: [label=X|tooltip]
if (lookaheadMatch[7]) {
title = lookaheadMatch[7].trim().slice(1,-1);
var pos=title.indexOf("|");
if (pos!=-1) { tooltip = title.substr(pos+1,title.length); title=title.substr(0,pos); }
if (title.substr(title.length-2,1)=="=") { key=title.substr(title.length-1,1); title=title.slice(0,-2); }
if (pos==-1) tooltip += " "+title; // default tooltip: "show/hide <title>"
}
// create the button
if (lookaheadMatch[3]) { // use "Hn" header format instead of button/link
var lvl=(lookaheadMatch[3].length>6)?6:lookaheadMatch[3].length;
var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,lookaheadMatch[6],title);
btn.onclick=onClickNestedSlider;
btn.setAttribute("href","javascript:;");
btn.setAttribute("title",tooltip);
}
else
var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,lookaheadMatch[6]);
// set extra button attributes
btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
btn.defOpen=lookaheadMatch[1]!=null; // save default open/closed state (boolean)
btn.keyparam=key; // save the access key letter ("" if none)
if (key.length) {
btn.setAttribute("accessKey",key); // init access key
btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
}
// "non-click" MouseOver open/close slider
if (lookaheadMatch[5]) btn.onmouseover=onClickNestedSlider;
// create slider panel
var panelClass=lookaheadMatch[4]?"floatingPanel":"sliderPanel";
var panel=createTiddlyElement(place,"div",null,panelClass,null);
panel.button = btn; // so the slider panel know which button it belongs to
panel.defaultPanelWidth=(lookaheadMatch[4] && lookaheadMatch[4].length>2)?lookaheadMatch[4].slice(1,-1):""; // save requested panel size
btn.sliderPanel=panel;
panel.style.display = show;
panel.style.width=panel.defaultPanelWidth;
// render slider (or defer until shown)
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
if ((show=="block")||!lookaheadMatch[9]) {
// render now if panel is supposed to be shown or NOT deferred rendering
w.subWikify(lookaheadMatch[8]?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
// align slider/floater position with button
adjustSliderPos(place,btn,panel,panelClass);
}
else {
var src = w.source.substr(w.nextMatch);
var endpos=findMatchingDelimiter(src,"+++","===");
panel.setAttribute("raw",src.substr(0,endpos));
panel.setAttribute("blockquote",lookaheadMatch[8]?"true":"false");
panel.setAttribute("rendered","false");
w.nextMatch += endpos+3;
if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
if (config.options.chkDebugLazySliderDefer) alert("deferred '"+title+"':\n\n"+panel.getAttribute("raw"));
}
}
}
}
)
// TBD: ignore 'quoted' delimiters (e.g., "{{{+++foo===}}}" isn't really a slider)
function findMatchingDelimiter(src,starttext,endtext) {
var startpos = 0;
var endpos = src.indexOf(endtext);
// check for nested delimiters
while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
// count number of nested 'starts'
var startcount=0;
var temp = src.substring(startpos,endpos-1);
var pos=temp.indexOf(starttext);
while (pos!=-1) { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
// set up to check for additional 'starts' after adjusting endpos
startpos=endpos+endtext.length;
// find endpos for corresponding number of matching 'ends'
while (startcount && endpos!=-1) {
endpos = src.indexOf(endtext,endpos+endtext.length);
startcount--;
}
}
return (endpos==-1)?src.length:endpos;
}
//}}}
//{{{
window.onClickNestedSlider=function(e)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
var theLabel = theTarget.firstChild.data;
var theSlider = theTarget.sliderPanel
var isOpen = theSlider.style.display!="none";
// if using default button labels, toggle labels
if (theLabel==">") theTarget.firstChild.data = "<";
else if (theLabel=="<") theTarget.firstChild.data = ">";
// if using default tooltips, toggle tooltips
if (theTarget.getAttribute("title")=="show")
theTarget.setAttribute("title","hide");
else if (theTarget.getAttribute("title")=="hide")
theTarget.setAttribute("title","show");
if (theTarget.getAttribute("title")=="show "+theLabel)
theTarget.setAttribute("title","hide "+theLabel);
else if (theTarget.getAttribute("title")=="hide "+theLabel)
theTarget.setAttribute("title","show "+theLabel);
// deferred rendering (if needed)
if (theSlider.getAttribute("rendered")=="false") {
if (config.options.chkDebugLazySliderRender)
alert("rendering '"+theLabel+"':\n\n"+theSlider.getAttribute("raw"));
var place=theSlider;
if (theSlider.getAttribute("blockquote")=="true")
place=createTiddlyElement(place,"blockquote");
wikify(theSlider.getAttribute("raw"),place);
theSlider.setAttribute("rendered","true");
}
// show/hide the slider
if(config.options.chkAnimate)
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
else
theSlider.style.display = isOpen ? "none" : "block";
// reset to default width (might have been changed via plugin code)
theSlider.style.width=theSlider.defaultPanelWidth;
// align slider/floater position with target button
if (!isOpen) adjustSliderPos(theSlider.parentNode,theTarget,theSlider,theSlider.className);
// if showing panel, set focus to first 'focus-able' element in panel
if (theSlider.style.display!="none") {
var ctrls=theSlider.getElementsByTagName("*");
for (var c=0; c<ctrls.length; c++) {
var t=ctrls[c].tagName.toLowerCase();
if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
{ ctrls[c].focus(); break; }
}
}
if (this.sliderCookie && this.sliderCookie.length) {
config.options[this.sliderCookie]=!isOpen;
if (config.options[this.sliderCookie]!=this.defOpen)
saveOptionCookie(this.sliderCookie);
else { // remove cookie if slider is in default display state
var ex=new Date(); ex.setTime(ex.getTime()-1000);
document.cookie = this.sliderCookie+"=novalue; path=/; expires="+ex.toGMTString();
}
}
return false;
}
// hijack animation handler 'stop' handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function() { this.coreStop(); this.element.style.overflow = "visible"; }
// adjust panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel,panelClass) {
if (panelClass=="floatingPanel") {
var left=0;
var top=btn.offsetHeight;
if (place.style.position!="relative") {
var left=findPosX(btn);
var top=findPosY(btn)+btn.offsetHeight;
var p=place; while (p && p.className!='floatingPanel') p=p.parentNode;
if (p) { left-=findPosX(p); top-=findPosY(p); }
}
if (left+panel.offsetWidth > getWindowWidth()) left=getWindowWidth()-panel.offsetWidth-10;
panel.style.left=left+"px"; panel.style.top=top+"px";
}
}
function getWindowWidth() {
if(document.width!=undefined)
return document.width; // moz (FF)
if(document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) )
return document.documentElement.clientWidth; // IE6
if(document.body && ( document.body.clientWidth || document.body.clientHeight ) )
return document.body.clientWidth; // IE4
if(window.innerWidth!=undefined)
return window.innerWidth; // IE - general
return 0; // unknown
}
//}}}
And just now came upon Saq Imtiaz's [["TiddlySnip" FireFox extension|http://tiddlysnip.com/]]
Refactored [[Resources]] and GettingStarted.
Just now discovered http://tiddlychatter.tiddlyspot.com/
Also [[presentation template|http://lewcid.googlepages.com/presentation_empty_full.html]] ([[see it in action|http://lewcid.googlepages.com/tots.html]]) and [[WebView|http://www.giffmex.org/webviewtwexample.html]] (gotta luv the editor functions here!).
Should peek http://tiddlyspot.com/ as well.
Dragged in the TiddlerNotesPlugin, so [[Notes]] works ... but I had noped to use it in AnonGreets, so visitors could leave notes anonymousely (i.e. the //principle of ''non-destructive contribution''//) but no such luck.
''NB'': Lots of posts to grapple with on [[Saq's "Tiddly Learning" blog Lewcid.org|http://lewcid.org/]]
Hot Dang! see AccordionMenuDemo ... using [[tw.lewcid.org/#AccordionMenuPlugin|http://tw.lewcid.org/#AccordionMenuPlugin]]
''//~ToDo//'': Get a consistent look between this and the slider style in [[Resources]].
NB: StartingAccordion is a variant of GettingStarted ... note how it should be multiline but //each link causes a newline// ... ''not right''.
And likewise //Hot Dang//: DropDownDemo from [[tw.lewcid.org/#DropDownMenuPlugin|http://tw.lewcid.org/#DropDownMenuPlugin]]
Created TestTabs ... neat!
''//Project//'':
I'm seeing some really fine plugins on sites that are a) stale (unedited since sometime in 2006) and b) not accessible //via// "Import". So: how to harvest from sites such as [[Jim Barr's fully enhanced TW|http://tiddlywikitips.com/]]?
I just did a manual grap of his [[Plugin listTags]] ... no evidence that it's working; no documentation of how it's used. ~HeyHo.
His [[list of internal macros|http://tiddlywikitips.com/#Internal Macros]] is useful, for e.g. listing all tiddlers with a certain tag:
<<tag journal>>
I just grabbed his [[list of internal macros|InternalMacros]]. (The ref links are relative, so that needs to be hacked.)
Meh ... grabbed [[Plugin SplashScreen]] but no joy.
Meh again ... grabbed [[Plugin ImportTiddlers]] and got "A script from "http://wiki.osmosoft.com" was denied UniversalBrowserRead privileges." and exceptions / errors.
Ok, so now I'm getting "Could not open local document: C:\buffer\ripplerap\tiddlywikitips_empty.html" ... which isn't even slightly helpful. ~HeyHo ...
<<importTiddlers inline>>
''//NB://'' I had to un-deploy the systemConfig tag (by changing it to systemConfigwas) because it clashes with the "Backstage" import function.
----
Neato ... I just found how to include another tiddler's contents inside a tiddler, e.g. here's [[subtabB1]]:
<<tiddler "subtabB1">>
----
<<tag journal>>
<<slider chkSliderOptionsPanel BasicRes 'Basic »' 'A list of sites'>>
<<slider chkSliderOptionsPanel AdvancedRes 'Advanced »' 'A list of sites'>>
<<slider chkSliderOptionsPanel ExporeRes 'To Be Explored »' 'A list of sites'>>
<<tag resources>>
Hope hope hope
So this is contents
!!!Getting an account on Lycos (tripod)
#Go to http://www.tripod.lycos.co.uk/
#Signup for an account
#Wait for your account verification email and verify your account
#When your account is verified, login to your account
#Go to ''My account'', below ''Take a tour'' on your left
#Go to bottom of the page and locate five icons (green and black)
#click on ''PHP4U''
#Click on ''Active PHP4U now''
#On this page, record down your database info. I use my test site as an example
{{{
Name: cctiddly_uk_db
Username: cctiddly
Password: no password needed
Host: localhost
}}}
!!!Config and upload your ccTiddly
*open your ''default.php'' under your ''config'' directory with your favorite editor
*Change the following variables to the values required (change
{{{
$tiddlyCfg['db']['host'] = "localhost"; //sql host
$tiddlyCfg['db']['login'] = "cctiddly"; //login name
$tiddlyCfg['db']['pass'] = ""; //login password
$tiddlyCfg['db']['name'] = "cctiddly_uk_db"; //db name
}}}
*because the MySQL on Lycos do not support ''set names'', disable utf-8 in your config file (set it to 0, available in v1.0 final)
{{{
$tiddlyCfg['pref']['utf8'] = 0;
}}}
<<tag requirements>>
[[all of the Internal Macro Tiddlers at TiddlyWikiTips.com|http://TiddlyWikiTips.com/index.html#[[Tip #12: TiddlyWiki Internal Macros]] TipAllTags TipCloseAll TipNewJournal TipNewTiddler TipPermaView TipSaveChanges TipSearch TipSlider TipTabbedContent TipTagPopUp TipTiddlerContents TipTimeline TipToday TipTWVersion]]
----
In addition to the excellent Plugins found here and throughout the TiddlyWiki world, TiddlyWiki contains some internal Macros that, for the most part, remain undocumented. They can offer lots of interesting possibilities when customizing your TiddlyWiki. The Macro list below was compiled from TiddlyWiki version 1.2.31. Click on a macro's description below to view more detail about each Macro including syntax, description, and examples!
|!Macro|!Description|!Syntax|
|allTags|[[List all Tags in a Tiddler|TipAllTags]]|{{{<}}}{{{<allTags>>}}}|
|closeAll|[[Close all displayed Tiddlers|TipCloseAll]]|{{{<}}}{{{<closeAll>>}}}|
|list all|[[List all Tiddlers in a Tiddler|TipListAll]]|{{{<}}}{{{<list all>>}}}|
|list missing|[[List all Missing Tiddlers in a Tiddler|TipListMissing]]|{{{<}}}{{{<list missing>>}}}|
|list orphans|[[List all orphaned Tiddlers in a Tiddler|TipListOrphans]]|{{{<}}}{{{<list orphans>>}}}|
|newJournal|[[Create new date & Time stamped Tiddler|TipNewJournal]]|{{{<}}}{{{<newJournal>>}}}|
|newTiddler|[[Create new Tiddler|TipNewTiddler]]|{{{<}}}{{{<newTiddler>>}}}|
|permaview|[[URL link for all open Tiddlers|TipPermaView]]|{{{<}}}{{{<permaview>>}}}|
|saveChanges |[[Save all TiddlyWiki changes|TipSaveChanges]]|{{{<}}}{{{<saveChanges>>}}}|
|search|[[Display a Search box|TipSearch]]|{{{<}}}{{{<search>>}}}|
|slider|[[Display a Slider|TipSlider]]|{{{<}}}{{{<slider sliderID sliderTiddler sliderLabel>>}}}|
|tabs|[[Display Tabbed content|TipTabbedContent]]|{{{<}}}{{{<tabs indentifier tabLabel tabName Tiddler>>}}}|
|tag|[[Display a Tag PopUp|TipTagPopUp]]|{{{<}}}{{{<tag tagName>>}}}|
|tiddler|[[Display inline contents of a Tiddler|TipTiddlerContents]]|{{{<}}}{{{<tiddler Tiddler>>}}}|
|timeline|[[Display Timeline in a Tiddler|TipTimeline]]|{{{<}}}{{{<timeline>>}}}|
|today|[[Dusplay Today's Date|TipToday]]|{{{<}}}{{{<today>>}}}|
|version|[[Display TiddlyWiki's version|TipTWVersion]]|{{{<}}}{{{<version>>}}}|
config.macros.listTags = { text: "Hello" };
config.macros.listTags.handler = function(place,macroName,params)
{
var tagged = store.getTaggedTiddlers(params[0]);
var ul = createTiddlyElement(place,"ul",null,null,"");
for(var r=0;r<tagged.length;r++)
{
var li = createTiddlyElement(ul,"li",null,null,"");
createTiddlyLink(li,tagged[r].title,true);
}
}
/***
''Inspired by [[TiddlyPom|http://www.warwick.ac.uk/~tuspam/tiddlypom.html]]''
|Name|SplashScreenPlugin|
|Created by|SaqImtiaz|
|Location|http://lewcid.googlepages.com/lewcid.html#SplashScreenPlugin|
|Version|0.21 |
|Requires|~TW2.08+|
!Description:
Provides a simple splash screen that is visible while the TW is loading.
!Installation
Copy the source text of this tiddler to your TW in a new tiddler, tag it with systemConfig and save and reload. The SplashScreen will now be installed and will be visible the next time you reload your TW.
!Customizing
Once the SplashScreen has been installed and you have reloaded your TW, the splash screen html will be present in the MarkupPreHead tiddler. You can edit it and customize to your needs.
!History
* 20-07-06 : version 0.21, modified to hide contentWrapper while SplashScreen is displayed.
* 26-06-06 : version 0.2, first release
!Code
***/
//{{{
var old_lewcid_splash_restart=restart;
restart = function()
{ if (document.getElementById("SplashScreen"))
document.getElementById("SplashScreen").style.display = "none";
if (document.getElementById("contentWrapper"))
document.getElementById("contentWrapper").style.display = "block";
old_lewcid_splash_restart();
if (splashScreenInstall)
{if(config.options.chkAutoSave)
{saveChanges();}
displayMessage("TW SplashScreen has been installed, please save and refresh your TW.");
}
}
var oldText = store.getTiddlerText("MarkupPreHead");
if (oldText.indexOf("SplashScreen")==-1)
{var siteTitle = store.getTiddlerText("SiteTitle");
var splasher='\n\n<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>'+siteTitle +'</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>';
if (! store.tiddlerExists("MarkupPreHead"))
{var myTiddler = store.createTiddler("MarkupPreHead");}
else
{var myTiddler = store.getTiddler("MarkupPreHead");}
myTiddler.set(myTiddler.title,oldText+splasher,config.options.txtUserName,null,null);
store.setDirty(true);
var splashScreenInstall = true;
}
//}}}
/***
''Import Tiddlers Plugin for TiddlyWiki version 1.2.x and 2.0''
^^author: Eric Shulman - ELS Design Studios
source: http://www.TiddlyTools.com/#ImportTiddlersPlugin
license: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^
When many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. It can also be very useful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)
!!!!!Inline interface (live)
<<<
<<importTiddlers inline>>
<<<
!!!!!Macro Syntax
<<<
{{{<<importTiddlers>>}}}
creates "import tiddlers" link. click to show/hide import control panel
{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content
{{{<<importTiddlers filter source quiet ask>>}}}
non-interactive 'automatic' import.
''filter'' determines which tiddlers will be automatically selected for importing. Use one of the following keywords:
>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler
>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)
>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.
''source'' is the location of the imported document. It can be either a local document or an URL:
>filename is any local path/file, in whatever format your system requires
>URL is any remote web location that starts with "http://" or "https://"
''"quiet"'' (optional)
>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.
''"ask"'' (optional)
>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.
''Special tag values: importReplace and importPublic''
By adding these special tags to an existing tiddler, you can precisely control whether or not to allow updates to that tiddler as well as decide which tiddlers in your document can be automatically imported by others.
*''For maximum safety, the default action is to prevent existing tiddlers from being unintentionally overwritten by incoming tiddlers.'' To allow an existing tiddler to be overwritten by an imported tiddler, you must tag the existing tiddler with ''<<tag importReplace>>''
*''For maximum privacy, the default action for //outgoing// tiddlers is to NOT automatically share your tiddlers with others.'' To allow a tiddler in your document to be shared via auto-import actions by others, you must tag it with ''<<tag importPublic>>''
//Note: these tags are only applied when using the auto-import processing. When using the interactive control panel, all tiddlers in the imported document are available in the listbox, regardless of their tag values.//
<<<
!!!!!Interactive Usage
<<<
When used interactively, a control panel is displayed consisting of an "import source document" filename input (text field plus a ''[Browse...]'' button), a listbox of available tiddlers, a "differences only" checkbox, an "add tags" input field and four push buttons: ''[open]'', ''[select all]'', ''[import]'' and ''[close]''.
Press ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//
Select one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.
''select: all, new, changes, or differences''
You can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:
>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document
>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)
''Import Tagging:''
Tiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.
''Skip, Rename, Merge, or Replace:''
When importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.
To bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.
//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//
''Import Report History''
When tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.
When the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.
If a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.
Note: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.
<<<
!!!!!Installation
<<<
copy/paste the following tiddlers into your document:
''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)
create/edit ''SideBarOptions'': (sidebar menu items)
^^Add "< < ImportTiddlers > >" macro^^
''Quick Installation Tip #1:''
If you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.
<<<
!!!!!Revision History
<<<
''2006.02.17 [2.6.0]''
Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.
''2006.02.16 [2.5.4]''
added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.
''2006.02.14 [2.5.3]''
FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()
''2006.02.10 [2.5.2]''
corrected unintended global variable in importReport().
''2006.02.05 [2.5.1]''
moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals
''2006.01.18 [2.5.0]''
added checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.
''2006.01.15 [2.4.1]''
added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic
''2006.01.15 [2.4.0]''
Added support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.
''2006.01.15 [2.3.2]''
Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)
''2006.01.15 [2.3.1]''
Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.
''2006.01.12 [2.3.0]''
Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.
''2006.01.11 [2.2.0]''
Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
''2006.01.09 [2.1.1]''
When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.
''2006.01.08 [2.1.0]''
IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.
''2006.01.06 [2.0.2]''
When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.
''2006.01.04 [2.0.1]''
When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.
''2005.12.27 [2.0.0]''
Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
''2005.12.22 [1.3.1]''
tweak formatting in importReport() and add 'discard report' link to output
''2005.12.03 [1.3.0]''
Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)
''2005.11.29 [1.2.1]''
fixed formatting of 'detail info' in importReport()
''2005.11.11 [1.2.0]''
added 'inline' param to embed controls in a tiddler
''2005.11.09 [1.1.0]''
only load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.
''2005.10.25 [1.0.5]''
fixed typo in importReport() that prevented reports from being generated
''2005.10.09 [1.0.4]''
combined documentation with plugin code instead of using separate tiddlers
''2005.08.05 [1.0.3]''
moved CSS and HTML definitions into plugin code instead of using separate tiddlers
''2005.07.27 [1.0.2]''
core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()
''2005.07.23 [1.0.1]''
added parameter checks and corrected addNotification() usage
''2005.07.20 [1.0.0]''
Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
// // Version
//{{{
version.extensions.importTiddlers = {major: 2, minor: 6, revision: 0, date: new Date(2006,2,17)};
//}}}
// // 1.2.x compatibility
//{{{
if (!window.story) window.story=window;
if (!store.getTiddler) store.getTiddler=function(title){return store.tiddlers[title]}
if (!store.addTiddler) store.addTiddler=function(tiddler){store.tiddlers[tiddler.title]=tiddler}
if (!store.deleteTiddler) store.deleteTiddler=function(title){delete store.tiddlers[title]}
//}}}
// // IE needs explicit global scoping for functions/vars called from browser events
//{{{
window.onClickImportButton=onClickImportButton;
window.loadImportFile=loadImportFile;
window.refreshImportList=refreshImportList;
//}}}
// // default cookie/option values
//{{{
if (!config.options.chkImportReport) config.options.chkImportReport=true;
//}}}
// // ''MACRO DEFINITION''
//{{{
config.macros.importTiddlers = { };
config.macros.importTiddlers = {
label: "import tiddlers",
prompt: "Copy tiddlers from another document",
countMsg: "%0 tiddlers selected for import",
src: "", // path/filename or URL of document to import
inbound: null, // hash-indexed array of tiddlers from other document
newTags: "", // text of tags added to imported tiddlers
addTags: true, // add new tags to imported tiddlers
listsize: 8, // # of lines to show in imported tiddler list
importTags: true, // include tags from remote source document when importing a tiddler
keepTags: true, // retain existing tags when replacing a tiddler
index: 0, // current processing index in import list
sort: "" // sort order for imported tiddler listbox
};
config.macros.importTiddlers.handler = function(place,macroName,params) {
// LINK WITH FLOATING PANEL
if (!params[0]) {
createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
return;
}
// INLINE TIDDLER CONTENT
if (params[0]=="inline") {
createImportPanel(place);
document.getElementById("importPanel").style.position="static";
document.getElementById("importPanel").style.display="block";
return;
}
// NON-INTERACTIVE BATCH MODE
switch (params[0]) {
case 'all':
case 'new':
case 'changes':
case 'updates':
var filter=params.shift();
break;
default:
var filter="updates";
break;
}
if (!params[0]||!params[0].length) return; // filename is required
config.macros.importTiddlers.src=params.shift();
var quiet=(params[0]=="quiet"); if (quiet) params.shift();
var ask=(params[0]=="ask"); if (ask) params.shift();
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
// load storeArea from a hidden IFRAME, then apply import rules and add/replace tiddlers
loadImportFile(config.macros.importTiddlers.src,filter,quiet,ask,autoImportTiddlers);
}
//}}}
// // ''READ TIDDLERS FROM ANOTHER DOCUMENT''
//{{{
function loadImportFile(src,filter,quiet,ask,callback) {
if (!quiet) clearMessage();
// LOCAL FILE
if ((src.substr(0,7)!="http://")&&(src.substr(0,8)!="https://")) {
if (!quiet) displayMessage("Opening local document: "+ src);
var txt=loadFile(src);
if(!txt) { if (!quiet) displayMessage("Could not open local document: "+src); }
else {
var s="<html><body>"+txt.substr(txt.indexOf('<div id="storeArea">'));
if (!quiet) displayMessage(txt.length+" bytes in document. ("+s.length+" bytes used for tiddler storage)");
config.macros.importTiddlers.inbound = readImportedTiddlers(convertUTF8ToUnicode(s));
var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;
if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);
if (callback) callback(src,filter,quiet,ask);
}
return;
}
// REMOTE FILE
var x; // XML object
try {x = new XMLHttpRequest()}
catch(e) {
try {x = new ActiveXObject("Msxml2.XMLHTTP")}
catch (e) {
try {x = new ActiveXObject("Microsoft.XMLHTTP")}
catch (e) { return }
}
}
x.onreadystatechange = function() {
if (x.readyState == 4) {
if (x.status == 200) {
var sa="<html><body>"+x.responseText.substr(x.responseText.indexOf('<div id="storeArea">'));
if (!quiet) displayMessage(x.responseText.length+" bytes in document. ("+sa.length+" bytes used for tiddler storage)");
config.macros.importTiddlers.inbound = readImportedTiddlers(sa);
var count=config.macros.importTiddlers.inbound?config.macros.importTiddlers.inbound.length:0;
if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);
if (callback) callback(src,filter,quiet,ask);
}
else
if (!quiet) displayMessage("Could not open remote document:"+ src+" (error="+x.status+")");
}
}
if (document.location.protocol=="file:") { // UniversalBrowserRead only works from a local file context
try {netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead')}
catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
}
if (!quiet) displayMessage("Opening remote document: "+ src);
try {
var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
x.open("GET",url,true);
x.overrideMimeType('text/html');
x.send(null);
}
catch (e) {
if (!quiet) {
displayMessage("Could not open remote document: "+src);
displayMessage(e.description?e.description:e.toString());
}
}
}
function readImportedTiddlers(txt)
{
var importedTiddlers = [];
// create frame
var f=document.getElementById("importFrame");
if (f) document.body.removeChild(f);
f=document.createElement("iframe");
f.id="importFrame";
f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
document.body.appendChild(f);
// get document
var d=f.document;
if (f.contentDocument) d=f.contentDocument; // For NS6
else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
// load source into document
d.open(); d.writeln(txt); d.close();
// read tiddler DIVs from storeArea DOM element
var importStore = [];
var importStoreArea = d.getElementById("storeArea");
if (!importStoreArea || !(importStore=importStoreArea.childNodes) || (importStore.length==0)) { return null; }
importStoreArea.normalize();
for(var t = 0; t < importStore.length; t++) {
var e = importStore[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && (e.id.substr(0,5) == "store"))
title = e.id.substr(5);
if(title && title != "") {
var theImported = new Tiddler();
theImported.loadFromDiv(e,title);
importedTiddlers.push(theImported);
}
}
return importedTiddlers;
}
//}}}
// // ''NON-INTERACTIVE IMPORT''
// // import all/new/changed tiddlers into store, replacing or adding tiddlers as needed
//{{{
function autoImportTiddlers(src,filter,quiet,ask)
{
var count=0;
if (config.macros.importTiddlers.inbound) for (var t=0;t<config.macros.importTiddlers.inbound.length;t++) {
var theImported = config.macros.importTiddlers.inbound[t];
var theExisting = store.getTiddler(theImported.title);
// only import tiddlers if tagged with "importPublic"
if (theImported.tags && theImported.tags.find("importPublic")==null)
{ config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report
// never import the "ImportedTiddlers" history from the other document...
if (theImported.title=='ImportedTiddlers')
{ config.macros.importTiddlers.inbound[t].status=""; continue; } // status=="" means don't show in report
// check existing tiddler for importReplace, or systemConfig tags
config.macros.importTiddlers.inbound[t].status="added"; // default - add any tiddlers not filtered out
if (store.tiddlerExists(theImported.title)) {
config.macros.importTiddlers.inbound[t].status="replaced";
if (!theExisting.tags||(theExisting.tags.find("importReplace")==null))
{ config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists (use importReplace to allow changes)"; continue; }
if ((theExisting.tags.find("systemConfig")!=null)||(theImported.tags.find("systemConfig")!=null))
config.macros.importTiddlers.inbound[t].status+=" - WARNING: an active systemConfig plugin has been added or updated";
}
// apply the all/new/changes/updates filter
if (filter!="all") {
if ((filter=="new") && store.tiddlerExists(theImported.title))
{ config.macros.importTiddlers.inbound[t].status="not imported - tiddler already exists"; continue; }
if ((filter=="changes") && !store.tiddlerExists(theImported.title))
{ config.macros.importTiddlers.inbound[t].status="not imported - new tiddler"; continue; }
if (store.tiddlerExists(theImported.title) && ((theExisting.modified.getTime()-theImported.modified.getTime())>=0))
{ config.macros.importTiddlers.inbound[t].status="not imported - tiddler is unchanged"; continue; }
}
// get confirmation if required
if (ask && !confirm("Import "+(theExisting?"updated":"new")+" tiddler '"+theImported.title+"'\nfrom "+src))
{ config.macros.importTiddlers.inbound[t].status="skipped - cancelled by user"; continue; }
// DO THE IMPORT!!
store.addTiddler(theImported); count++;
}
importReport(quiet); // generate a report (as needed) and display it if not 'quiet'
if (count) store.setDirty(true);
// always show final message when tiddlers were actually imported
if (!quiet||count) displayMessage("Imported "+count+" tiddler"+(count!=1?"s":"")+" from "+src);
}
//}}}
// // ''REPORT GENERATOR''
//{{{
function importReport(quiet)
{
if (!config.macros.importTiddlers.inbound) return;
// DEBUG alert('importReport: start');
// if import was not completed, the Ask panel will still be open... close it now.
var askpanel=document.getElementById('importAskPanel'); if (askpanel) askpanel.style.display='none';
// get the alphasorted list of tiddlers
var tiddlers = config.macros.importTiddlers.inbound;
tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
// gather the statistics
var count=tiddlers.length;
var added=0; var replaced=0; var renamed=0; var skipped=0; var merged=0;
for (var t=0; t<count; t++)
if (tiddlers[t].status)
{
if (tiddlers[t].status=='added') added++;
if (tiddlers[t].status.substr(0,7)=='skipped') skipped++;
if (tiddlers[t].status.substr(0,6)=='rename') renamed++;
if (tiddlers[t].status.substr(0,7)=='replace') replaced++;
if (tiddlers[t].status.substr(0,6)=='merged') merged++;
}
var omitted=count-(added+replaced+renamed+skipped+merged);
// DEBUG alert('stats done: '+count+' total, '+added+' added, '+skipped+' skipped, '+renamed+' renamed, '+replaced+' replaced, '+merged+' merged');
// skip the report if nothing was imported
if (added+replaced+renamed+merged==0) return;
// skip the report if not desired by user
if (!config.options.chkImportReport) {
// reset status flags
for (var t=0; t<count; t++) config.macros.importTiddlers.inbound[t].status="";
// refresh display since tiddlers have been imported
store.notifyAll();
// quick message area summary report
var msg=(added+replaced+renamed+merged)+' of '+count+' tiddler'+((count!=1)?'s':"");
msg+=' imported from '+config.macros.importTiddlers.src.replace(/\\/g,'/')
displayMessage(msg);
return;
}
// create the report tiddler (if not already present)
var tiddler = store.getTiddler('ImportedTiddlers');
if (!tiddler) // create new report tiddler if it doesn't exist
{
tiddler = new Tiddler();
tiddler.title = 'ImportedTiddlers';
tiddler.text = "";
}
// format the report header
var now = new Date();
var newText = "";
newText += "On "+now.toLocaleString()+", "+config.options.txtUserName+" imported tiddlers from\n";
newText += "[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\n";
newText += "<"+"<"+"<\n";
newText += "Out of "+count+" tiddler"+((count!=1)?"s ":" ")+" in {{{"+config.macros.importTiddlers.src.replace(/\\/g,'/')+"}}}:\n";
if (added+renamed>0)
newText += (added+renamed)+" new tiddler"+(((added+renamed)!=1)?"s were":" was")+" added to your document.\n";
if (merged>0)
newText += merged+" tiddler"+((merged!=1)?"s were":" was")+" merged with "+((merged!=1)?"":"an ")+"existing tiddler"+((merged!=1)?"s":"")+".\n";
if (replaced>0)
newText += replaced+" existing tiddler"+((replaced!=1)?"s were":" was")+" replaced.\n";
if (skipped>0)
newText += skipped+" tiddler"+((skipped!=1)?"s were":" was")+" skipped after asking.\n";
if (omitted>0)
newText += omitted+" tiddler"+((omitted!=1)?"s":"")+((omitted!=1)?" were":" was")+" not imported.\n";
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newText += "imported tiddlers were tagged with: \""+config.macros.importTiddlers.newTags+"\"\n";
// output the tiddler detail and reset status flags
for (var t=0; t<count; t++)
if (tiddlers[t].status!="")
{
newText += "#["+"["+tiddlers[t].title+"]"+"]";
newText += ((tiddlers[t].status!="added")?("^^\n"+tiddlers[t].status+"^^"):"")+"\n";
config.macros.importTiddlers.inbound[t].status="";
}
newText += "<"+"<"+"<\n";
// output 'discard report' link
newText += "<html><input type=\"button\" href=\"javascript:;\" ";
newText += "onclick=\"story.closeTiddler('"+tiddler.title+"'); store.deleteTiddler('"+tiddler.title+"');\" ";
newText += "value=\"discard report\"></html>";
// update the ImportedTiddlers content and show the tiddler
tiddler.text = newText+((tiddler.text!="")?'\n----\n':"")+tiddler.text;
tiddler.modifier = config.options.txtUserName;
tiddler.modified = new Date();
store.addTiddler(tiddler);
if (!quiet) story.displayTiddler(null,"ImportedTiddlers",1,null,null,false);
story.refreshTiddler("ImportedTiddlers",1,true);
// refresh the display
store.notifyAll();
}
//}}}
// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
if (!e) var e = window.event;
var parent=resolveTarget(e).parentNode;
var panel = document.getElementById("importPanel");
if (panel==undefined || panel.parentNode!=parent)
panel=createImportPanel(parent);
var isOpen = panel.style.display=="block";
if(config.options.chkAnimate)
anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
else
panel.style.display = isOpen ? "none" : "block" ;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
// // Create control panel: HTML, CSS, register for notification
//{{{
function createImportPanel(place) {
var panel=document.getElementById("importPanel");
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(config.macros.importTiddlers.css,"importTiddlers");
panel=createTiddlyElement(place,"span","importPanel",null,null)
panel.innerHTML=config.macros.importTiddlers.html;
store.addNotification(null,refreshImportList); // refresh listbox after every tiddler change
refreshImportList();
return panel;
}
//}}}
// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
padding: 0.5em; margin:0em; text-align:left; font-size: 8pt;\
background-color: #eee; color:#000000; \
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px; -moz-border-radius:1em;\
}\
#importPanel a { color:#009; }\
#importPanel input { width: 98%; margin: 1px; font-size:8pt; }\
#importPanel select { width: 98%; margin: 1px; font-size:8pt; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#importAskPanel { display:none; margin:0.5em 0em 0em 0em; }\
';
//}}}
// // HTML
//{{{
config.macros.importTiddlers.html = '\
<span style="float:left; padding:1px; white-space:nowrap">\
import from source document\
</span>\
<span style="float:right; padding:1px; white-space:nowrap">\
<input type=checkbox id="chkImportReport" checked style="height:1em; width:auto"\
onClick="config.options[\'chkImportReport\']=this.checked;">create a report\
</span>\
<input type="file" id="fileImportSource" size=56\
onKeyUp="config.macros.importTiddlers.src=this.value"\
onChange="config.macros.importTiddlers.src=this.value;">\
<span style="float:left; padding:1px; white-space:nowrap">\
select:\
<a href="JavaScript:;" id="importSelectAll"\
onclick="onClickImportButton(this)" title="select all tiddlers">\
all </a>\
<a href="JavaScript:;" id="importSelectNew"\
onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\
added </a> \
<a href="JavaScript:;" id="importSelectChanges"\
onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\
changes </a> \
<a href="JavaScript:;" id="importSelectDifferences"\
onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\
differences </a> \
<a href="JavaScript:;" id="importToggleFilter"\
onclick="onClickImportButton(this)" title="show/hide selection filter">\
filter </a> \
</span>\
<span style="float:right; padding:1px; white-space:nowrap">\
<a href="JavaScript:;" id="importListSmaller"\
onclick="onClickImportButton(this)" title="reduce list size">\
– </a>\
<a href="JavaScript:;" id="importListLarger"\
onclick="onClickImportButton(this)" title="increase list size">\
+ </a>\
<a href="JavaScript:;" id="importListMaximize"\
onclick="onClickImportButton(this)" title="maximize/restore list size">\
= </a>\
</span>\
<select id="importList" size=8 multiple\
onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<input type=checkbox id="chkAddTags" checked style="height:1em; width:auto"\
onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \
<input type=checkbox id="chkImportTags" checked style="height:1em; width:auto"\
onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \
<input type=checkbox id="chkKeepTags" checked style="height:1em; width:auto"\
onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags\
<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\
<div align=center>\
<input type=button id="importOpen" class="importButton" style="width:32%" value="open"\
onclick="onClickImportButton(this)">\
<input type=button id="importStart" class="importButton" style="width:32%" value="import"\
onclick="onClickImportButton(this)">\
<input type=button id="importClose" class="importButton" style="width:32%" value="close"\
onclick="onClickImportButton(this)">\
</div>\
<div id="importAskPanel">\
tiddler already exists:\
<input type=text id="importNewTitle" size=15 autocomplete=off">\
<div align=center>\
<input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\
onclick="onClickImportButton(this)">\
<input type=button id="importRename" class="importButton" style="width:23%" value="rename"\
onclick="onClickImportButton(this)">\
<input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\
onclick="onClickImportButton(this)">\
<input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\
onclick="onClickImportButton(this)">\
</div>\
</div>\
';
//}}}
// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
var theList = document.getElementById("importList");
if (!theList) return;
// if nothing to show, reset list content and size
if (!config.macros.importTiddlers.inbound)
{
while (theList.length > 0) { theList.options[0] = null; }
theList.options[0]=new Option('please open a document...',"",false,false);
theList.size=config.macros.importTiddlers.listsize;
return;
}
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading
if (selectedIndex==1) config.macros.importTiddlers.sort='title';
if (selectedIndex==2) config.macros.importTiddlers.sort='modified';
if (selectedIndex==3) config.macros.importTiddlers.sort='tags';
if (selectedIndex>3) {
// display selected tiddler count
for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
return; // no refresh needed
}
// get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)
var tiddlers=config.macros.importTiddlers.inbound;
tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
// clear current list contents
while (theList.length > 0) { theList.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);
// output the tiddler list
switch(config.macros.importTiddlers.sort)
{
case "title":
for(var t = 0; t < tiddlers.length; t++)
theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
break;
case "modified":
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
var lastSection = "";
for(var t = 0; t < tiddlers.length; t++) {
var tiddler = tiddlers[t];
var theSection = tiddler.modified.toLocaleDateString();
if (theSection != lastSection) {
theList.options[i++] = new Option(theSection,"",false,false);
lastSection = theSection;
}
theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
}
break;
case "tags":
var theTitles = {}; // all tiddler titles, hash indexed by tag value
var theTags = new Array();
for(var t=0; t<tiddlers.length; t++) {
var title=tiddlers[t].title;
var tags=tiddlers[t].tags;
for(var s=0; s<tags.length; s++) {
if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
theTitles[tags[s]].push(title);
}
}
theTags.sort();
for(var tagindex=0; tagindex<theTags.length; tagindex++) {
var theTag=theTags[tagindex];
theList.options[i++]=new Option(theTag,"",false,false);
for(var t=0; t<theTitles[theTag].length; t++)
theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
theList.selectedIndex=selectedIndex; // select current control item
if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;
if (theList.size>theList.options.length) theList.size=theList.options.length;
}
//}}}
// // Control interactions
//{{{
function onClickImportButton(which)
{
// DEBUG alert(which.id);
var theList = document.getElementById('importList');
if (!theList) return;
var thePanel = document.getElementById('importPanel');
var theAskPanel = document.getElementById('importAskPanel');
var theNewTitle = document.getElementById('importNewTitle');
var count=0;
switch (which.id)
{
case 'fileImportSource':
case 'importOpen': // load import source into hidden frame
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
if (config.macros.importTiddlers.src=="") break;
// Load document into hidden iframe so we can read it's DOM and fill the list
loadImportFile(config.macros.importTiddlers.src,"all",null,null,function(src,filter,quiet,ask){window.refreshImportList(0);});
break;
case 'importSelectAll': // select all tiddler list items (i.e., not headings)
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
if (theList.options[t].value=="") continue;
theList.options[t].selected=true;
count++;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectNew': // select tiddlers not in current document
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importToggleFilter': // show/hide filter
case 'importFilter': // apply filter
alert("coming soon!");
break;
case 'importStart': // initiate the import processing
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.index=0;
config.macros.importTiddlers.index=importTiddlers(0);
importStopped();
break;
case 'importClose': // unload imported tiddlers or hide the import control panel
// if imported tiddlers not loaded, close the import control panel
if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
break;
case 'importSkip': // don't import the tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status='skipped after asking'; // mark item as skipped
theAskPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item
importStopped();
break;
case 'importRename': // change name of imported tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status = 'renamed from '+theImported.title; // mark item as renamed
theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title
theItem.value = theNewTitle.value; // change the listbox item text
theItem.text = theNewTitle.value; // change the listbox item text
theAskPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importMerge': // join existing and imported tiddler content
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
var theText = theExisting.text+'\n----\n^^merged from: [['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\n^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
var theDate = new Date();
var theTags = theExisting.getTags()+' '+theImported.getTags();
theImported.set(null,theText,null,theDate,theTags);
theImported.status = 'merged with '+theExisting.title; // mark item as merged
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");
theImported.status += ' by '+theExisting.modifier;
theAskPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item
importStopped();
break;
case 'importReplace': // substitute imported tiddler for existing tiddler
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
theImported.status = 'replaces '+theExisting.title; // mark item for replace
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY hh:mm:ss");
theImported.status += ' by '+theExisting.modifier;
theAskPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importListSmaller': // decrease current listbox size, minimum=5
if (theList.options.length==1) break;
theList.size-=(theList.size>5)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListLarger': // increase current listbox size, maximum=number of items in list
if (theList.options.length==1) break;
theList.size+=(theList.size<theList.options.length)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListMaximize': // toggle listbox size between current and maximum
if (theList.options.length==1) break;
theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;
break;
}
}
//}}}
// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
if (!config.macros.importTiddlers.inbound) return -1;
var theList = document.getElementById('importList');
if (!theList) return;
var t;
// if starting new import, reset import status flags
if (startIndex==0)
for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)
config.macros.importTiddlers.inbound[t].status="";
for (var i=startIndex; i<theList.options.length; i++)
{
// if list item is not selected or is a heading (i.e., has no value), skip it
if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))
continue;
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==t) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theImported.title);
// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
if (theImported.status=="added")
continue;
// don't import the "ImportedTiddlers" history from the other document...
if (theImported.title=='ImportedTiddlers')
continue;
// if tiddler exists and import not marked for replace or merge, stop importing
if (theExisting && (theImported.status.substr(0,7)!="replace") && (theImported.status.substr(0,5)!="merge"))
return i;
// assemble tags (remote + existing + added)
var newTags = "";
if (config.macros.importTiddlers.importTags)
newTags+=theImported.getTags() // import remote tags
if (config.macros.importTiddlers.keepTags && theExisting)
newTags+=" "+theExisting.getTags(); // keep existing tags
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newTags+=" "+config.macros.importTiddlers.newTags; // add new tags
theImported.set(null,null,null,null,newTags.trim());
// set the status to 'added' (if not already set by the 'ask the user' UI)
theImported.status=(theImported.status=="")?'added':theImported.status;
// do the import!
store.addTiddler(theImported);
store.setDirty(true);
}
return(-1); // signals that we really finished the entire list
}
//}}}
//{{{
function importStopped()
{
var theList = document.getElementById('importList');
var theNewTitle = document.getElementById('importNewTitle');
if (!theList) return;
if (config.macros.importTiddlers.index==-1)
importReport(); // import finished... generate the report
else
{
// DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);
// import collision... show the ask panel and set the title edit field
document.getElementById('importAskPanel').style.display='block';
theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;
}
}
//}}}
/***
|''Name:''|AccordionMenuPlugin|
|''Description:''|Turn an unordered list into an accordion style menu|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#AccordionMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.0|
|''Date:''|03/11/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|
!!Usage:
* put {{{<<accordion>>}}} on the line after your unordered list
!!Customizing:
* customize the css via the shadow tiddler StyleSheetAccordionMenuPlugin
* or give the list a custom class by passing the classes as parameters to the macro.
** Eg: {{{<<accordion ClassName1 ClassName2>>}}}
!!Examples:
*[[AccordionMenuPluginDemo]]
***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.accordion={
dropchar : " \u00BB",
handler : function(place,macroName,params,wikifier,paramString,tiddler){
list = findRelated(place.lastChild,"UL","tagName","previousSibling");
if (!list)
return;
addClass(list,"accordion");
if (params.length){
addClass(list,paramString);
}
this.fixLinks(list.childNodes);
},
fixLinks : function(els){
for (var i=0; i<els.length; i++){
if(els[i].tagName.toLowerCase()=="li"){
var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
if(!link){
var ih = els[i].firstChild.data;
els[i].removeChild(els[i].firstChild);
link = createTiddlyElement(null,"a",null,null,ih+this.dropchar,{href:"javascript:;"});
els[i].insertBefore(link,els[i].firstChild);
}
else{
link.firstChild.data = link.firstChild.data + this.dropchar;
removeClass(link,"tiddlyLinkNonExisting");
}
link.onclick = this.show;
}
}
},
show : function(e){
var list = this.parentNode.parentNode;
var els = list.childNodes;
for (var i=0; i<els.length; i++){
removeClass(els[i],"accordion-active");
}
addClass(this.parentNode,"accordion-active");
}
};
config.shadowTiddlers["StyleSheetAccordionMenuPlugin"] = "/*{{{*/\n"+
"ul.accordion, ul.accordion li, ul.accordion li ul {margin:0; padding:0; list-style-type:none;text-align:left;}\n"+
"ul.accordion li ul {display:none;}\n"+
"ul.accordion li.accordion-active ul {display:block;}\n"+
"\n"+
"ul.accordion li.accordion-active a {cursor:default;}\n"+
"ul.accordion li.accordion-active ul li a{cursor:pointer;}\n"+
"\n"+
"ul.accordion a {display:block; padding:0.5em;}\n"+
"ul.accordion li a.tiddlyLink, ul.accordion li a.tiddlyLinkNonExisting, ul.accordion li a {font-weight:bold;}\n"+
"ul.accordion li a {background:#3278FC; color:#FFF; border-bottom:1px solid #fff;}\n"+
"ul.accordion li.accordion-active a, ul.accordion li a:hover {background:#00558F;color:#FFF;}\n"+
"\n"+
"ul.accordion li ul li{display:inline-block;overflow:hidden;}\n"+
"ul.accordion li.accordion-active ul li {background:#eff3fa; color:#000; padding:0em;}\n"+
"ul.accordion li.accordion-active ul li div {padding:1em 1.5em; background:#eff3fa;}\n"+
"ul.accordion li.accordion-active ul a{background:#eff3fa; color:#000; padding:0.5em 0.5em 0.5em 1.0em;border:none;}\n"+
"ul.accordion li.accordion-active ul a:hover {background:#e0e8f5; color:#000;}\n" +
"/*}}}*/";
store.addNotification("StyleSheetAccordionMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/
@@display:none;clear:both;@@
''Creating a navigation menu using the AccordionMenuPlugin is as simple as:''
# writing a two level unordered list using ~TiddlyWiki syntax
# and placing {{{<<accordion>>}}} on the line after it.
Example:
{{{
* Section 1
** [[Link1]]
** [[Link2]]
** [[Link3]]
*Section 2
** [[Link4]]
** [[Link5]]
** [[Link6]]
*Section 3
**[[Link7]]
**[[Link8]]
**[[Link9]]
<<accordion>>
}}}
gives:
* Section 1
** [[Link1]]
** [[Link2]]
** [[Link3]]
*Section 2
** [[Link4]]
** [[Link5]]
** [[Link6]]
*Section 3
**[[Link7]]
**[[Link8]]
**[[Link9]]
<<accordion>>
''The AccordionMenuPlugin was written with navigation menu's in mind but can be put to other uses as well. ''
By wrapping the content in a DIV, you can have multi-line content as well. Example:
{{{
* [[section1]]
**{{myclass{
Praesent posuere sodales tortor. Mauris ut erat non lacus semper porta. Mauris enim.
Phasellus tempor, metus ut dapibus lobortis, leo magna ornare metus, et pellentesque neque massa eget turpis.
Proin nec tellus. Donec aliquet.
Nullam sed leo bibendum justo rutrum rhoncus.}}}
* section2
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
* section3
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
}}}
gives you:
* [[section1]]
**{{myclass{
Praesent posuere sodales tortor. Mauris ut erat non lacus semper porta. Mauris enim.
Phasellus tempor, metus ut dapibus lobortis, leo magna ornare metus, et pellentesque neque massa eget turpis.
Proin nec tellus. Donec aliquet.
Nullam sed leo bibendum justo rutrum rhoncus.}}}
* section2
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
* section3
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
<<accordion>>
@@display:none;clear:both;@@
*Of interest:
**{{myclass{
*[[TWFaq at TiddlySpot|http://twfaq.tiddlyspot.com/]] and [[CheatSheet (PDF)|http://nothickmanuals.info/lib/exe/fetch.php/cheatsheets:tiddlywiki_cheatsheet.pdf]]
*[[Daniel Baird's UserGuide|http://danielbaird.com/tiddlywikiguides/userguide-sample.html#TiddlyWiki User's Guide]]
*[[TW Resources on TiddlyWiki.org's Wiki|http://www.tiddlywiki.org/wiki/TiddlyWiki_Resources]]
*[[Jim Barr's fully enhanced TW|http://tiddlywikitips.com/]]
}}}
*Advanced:
**{{myclass{
*[[Plugin Development|http://tiddlywiki.org/wiki/Plugin_Development]]
}}}
*To Be Explored:
**{{myclass{
*[["Tiddler Parts" plugin|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin]] by [[Udo Borkowski|http://www.abego-software.de/]] (see also [[list of his plugins|http://tiddlywiki.abego-software.de/#Plugins]])
*[[FND's DevPad|http://devpad.tiddlyspot.com/]]
*[[Some useful reference stuff by Jules|http://knighjm.googlepages.com/knightnet-default-tw.html#Reference]] including lists of built-in macros, formatting rules and useful javascript methods for developers.
*[[Repository for BidiX's TiddlyWiki Extensions|http://tiddlywiki.bidix.info/]]
*[[Extension Repository|http://tw.lewcid.org/]] from [[LewCid.org|http://lewcid.org/]]
}}}
<<accordion>>
<<tag demo>>
* Section 1
** [[Link1]]
** [[Link2]]
** [[Link3]]
*Section 2
** [[Link4]]
** [[Link5]]
** [[Link6]]
*Section 3
**[[Link7]]
**[[Link8]]
**[[Link9]]
<<accordion>>
MultiLine:
* [[section1]]
**{{myclass{
Praesent posuere sodales tortor. Mauris ut erat non lacus semper porta. Mauris enim.
Phasellus tempor, metus ut dapibus lobortis, leo magna ornare metus, et pellentesque neque massa eget turpis.
Proin nec tellus. Donec aliquet.
Nullam sed leo bibendum justo rutrum rhoncus.}}}
* section2
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
* section3
**{{myclass{
Donec rhoncus sem eget urna.
Aenean tempor dolor vitae nisi.
Donec leo urna, placerat porttitor, auctor ut, volutpat a, purus,
Etiam eu sapien id nulla malesuada scelerisque.
Maecenas rhoncus, nibh ut aliquam consequat, mi odio luctus sem, eu lobortis dolor neque nec lectus. }}}
<<accordion>>
<<tag demo>>
/***
|''Name:''|DropDownMenuPlugin|
|''Description:''|Create dropdown menus from unordered lists|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#DropDownMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|11/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|
!!Usage:
* create a two-level unordered list using wiki syntax, and place {{{<<dropMenu>>}}} on the line after it.
* to create a vertical menu use {{{<<dropMenu vertical>>}}} instead.
* to assign custom classes to the list, just pass them as parameters to the macro {{{<<dropMenu className1 className2 className3>>}}}
!!Features:
*Supports just a single level of drop-downs, as anything more usually provides a poor experience for the user.
* Very light weight, about 1.5kb of JavaScript and 4kb of CSS.
* Comes with two built in css 'themes', the default horizontal and vertical.
!!Customizing:
* to customize the appearance of the menu's, you can either add a custom class as described above or, you can edit the CSS via the StyleSheetDropDownMenu shadow tiddler.
!!Examples:
* [[DropDownMenuDemo]]
***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.dropMenu={
dropdownchar: "\u25bc",
handler : function(place,macroName,params,wikifier,paramString,tiddler){
list = findRelated(place.lastChild,"UL","tagName","previousSibling");
if (!list)
return;
addClass(list,"suckerfish");
if (params.length){
addClass(list,paramString);
}
this.fixLinks(list);
},
fixLinks : function(el){
var els = el.getElementsByTagName("li");
for(var i = 0; i < els.length; i++) {
if(els[i].getElementsByTagName("ul").length>0){
var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
if(!link){
var ih = els[i].firstChild.data;
els[i].removeChild(els[i].firstChild);
var d = createTiddlyElement(null,"a",null,null,ih+this.dropdownchar,{href:"javascript:;"});
els[i].insertBefore(d,els[i].firstChild);
}
else{
link.firstChild.data = link.firstChild.data + this.dropdownchar;
removeClass(link,"tiddlyLinkNonExisting");
}
}
els[i].onmouseover = function() {
addClass(this, "sfhover");
};
els[i].onmouseout = function() {
removeClass(this, "sfhover");
};
}
}
};
config.shadowTiddlers["StyleSheetDropDownMenuPlugin"] =
"/*{{{*/\n"+
"/***** LAYOUT STYLES - DO NOT EDIT! *****/\n"+
"ul.suckerfish, ul.suckerfish ul {\n"+
" margin: 0;\n"+
" padding: 0;\n"+
" list-style: none;\n"+
" line-height:1.4em;\n"+
"}\n\n"+
"ul.suckerfish li {\n"+
" display: inline-block; \n"+
" display: block;\n"+
" float: left; \n"+
"}\n\n"+
"ul.suckerfish li ul {\n"+
" position: absolute;\n"+
" left: -999em;\n"+
"}\n\n"+
"ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {\n"+
" left: auto;\n"+
"}\n\n"+
"ul.suckerfish ul li {\n"+
" float: none;\n"+
" border-right: 0;\n"+
" border-left:0;\n"+
"}\n\n"+
"ul.suckerfish a, ul.suckerfish a:hover {\n"+
" display: block;\n"+
"}\n\n"+
"ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}\n"+
"/**** END LAYOUT STYLES *****/\n"+
"\n\n"+
"/**** COLORS AND APPEARANCE - DEFAULT *****/\n"+
"ul.suckerfish li a {\n"+
" padding: 0.5em 1.5em;\n"+
" color: #FFF;\n"+
" background: #0066aa;\n"+
" border-bottom: 0;\n"+
" font-weight:bold;\n"+
"}\n\n"+
"ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{\n"+
" background: #00558F;\n"+
"}\n\n"+
"ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{\n"+
" color: #000;\n"+
" background: #eff3fa;\n"+
" border-top:1px solid #FFF;\n"+
"}\n\n"+
"ul.suckerfish ul li a:hover {\n"+
" background: #e0e8f5;\n"+
"}\n\n"+
"ul.suckerfish li a{\n"+
" width:9em;\n"+
"}\n\n"+
"ul.suckerfish ul li a, ul.suckerfish ul li a:hover{\n"+
" display:inline-block;\n"+
" width:9em;\n"+
"}\n\n"+
"ul.suckerfish li {\n"+
" border-left: 1px solid #00558F;\n"+
"}\n"+
"/***** END COLORS AND APPEARANCE - DEFAULT *****/\n"+
"\n\n"+
"/***** LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
"ul.suckerfish.vertical li{\n"+
" width:10em;\n"+
" border-left: 0px solid #00558f;\n"+
"}\n\n"+
"ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {\n"+
" border-left: 0.8em solid #00558f;\n"+
"}\n\n"+
"ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a, ul.suckerfish.vertical li.sfhover a:hover{\n"+
" width:8em;\n"+
"}\n\n"+
"ul.suckerfish.vertical {\n"+
" width:10em; text-align:left;\n"+
" float:left;\n"+
"}\n\n"+
"ul.suckerfish.vertical li a {\n"+
" padding: 0.5em 1em 0.5em 1em;\n"+
" border-top:1px solid #fff;\n"+
"}\n\n"+
"ul.suckerfish.vertical, ul.suckerfish.vertical ul {\n"+
" line-height:1.4em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { \n"+
" margin: -2.4em 0 0 10.9em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {\n"+
" border: 0px solid #FFF;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{\n"+
" padding-right:1.1em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {\n"+
" border-bottom:1px solid #fff;\n"+
"}\n\n"+
"/***** END LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
"/*}}}*/";
store.addNotification("StyleSheetDropDownMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
|Version|1.2.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|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.''
!!!!!Documentation
>see [[TaggedTemplateTweakInfo]]
!!!!!Revisions
<<<
2008.04.01 [1.2.0] added support for using systemTheme section-based template definitions (requested by Phil Hawksworth)
2008.01.22 [*.*.*] plugin size reduction - documentation moved to [[TaggedTemplateTweakInfo]]
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag. Allows new custom tags to be used without requiring code changes to this plugin.
| please see [[TaggedTemplateTweakInfo]] for previous revision details |
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.taggedTemplate= {major: 1, minor: 2, revision: 0, date: new Date(2008,4,1)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
// get default template from core
var template=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
// if the tiddler to be rendered doesn't exist yet, just return core result
var tiddler=store.getTiddler(title); if (!tiddler) return template;
// look for template whose prefix matches a tag on this tiddler
for (i=0; i<tiddler.tags.length; i++) {
var t=tiddler.tags[i]+template; // add tag prefix
var c=t.substr(0,1).toUpperCase()+t.substr(1); // capitalized for WikiWord title
var s=config.options.txtTheme+"##"; // systemTheme section prefix
if (store.tiddlerExists(t)) { template=t; break; }
if (store.tiddlerExists(c)) { template=c; break; }
if (store.getTiddlerText(s+t)) { template=s+t; break; }
if (store.getTiddlerText(s+c)) { template=s+c; break; }
}
return template;
}
//}}}
/***
|''Name:''|TiddlerNotesPlugin|
|''Description:''|Add notes to tiddlers without modifying the original content|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#TiddlerNotesPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|26/10/07|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.3|
!!Concept:
*The TiddlerNotesPlugin allows you to add notes to tiddlers, without needing to edit the original tiddler. This means that your original content will remain unaltered, and if you update it in the future, you won’t lose your notes. Notes are stored in separate tiddlers, but can be viewed and edited from within the original tiddler.
*For a tiddler titled "~MySlide", the notes are by default saved in a tiddler titled "~MySlide-Notes" and is given a tag of "Notes". The suffix and tags of the notes tiddlers are customizable. You can have one or multiple notes per tiddlers. So it is possible to have for example, teacher's notes and student's notes in the same file.
*Notes can be configured to start off blank, or pre-filled with the contents of the original tiddler.
!!Usage:
*{{{<<notes>>}}} is the simplest usage form.
* additional optional parameters include:
**{{{heading:}}} the heading to use for the notes box
**{{{tag:}}} the tag to be given to the notes tiddler
**{{{suffix:}}} the suffix to be used when naming the notes tiddler
* a full macro call could look like: {{{<<notes heading:"My Notes" tag:"NoteTiddlers" suffix:"Comments">>}}}
* To avoid adding {{{<<notes>>}}} to each tiddler you want notes for, you could add the macro call to the ViewTemplate
** below the line {{{<div class='viewer' macro='view text wikified'></div>}}} add the following line: <br> {{{<div class='viewer' macro='notes'></div>}}}
** Used in combination with the ~HideWhenPlugin or ~PublisherPlugin, you could have notes be shown only for tiddlers with specific tags. The ~PublisherPlugin would allow you for instance to only have the ~TeachersNotes visible to the teacher, and the ~StudentsNotes for the same tiddler visible to the Student.
!!Configuration
*<<option chkPrefillNotes>> Enable to pre-fill notes with the original tiddler's contents
!!Demo:
* [[MySlide]]
***/
// /%
//!BEGIN-PLUGIN-CODE
if (!config.options.chkPrefillNotes)
config.options.chkPrefillNotes = false;
function createTiddlyElement(theParent,theElement,theID,theClass,theText,attribs)
{
var e = document.createElement(theElement);
if(theClass != null)
e.className = theClass;
if(theID != null)
e.setAttribute("id",theID);
if(theText != null)
e.appendChild(document.createTextNode(theText));
if(attribs){
for(var n in attribs){
e.setAttribute(n,attribs[n]);
}
}
if(theParent != null)
theParent.appendChild(e);
return e;
}
function createTiddlyButton(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey,attribs)
{
var theButton = document.createElement("a");
if(theAction) {
theButton.onclick = theAction;
theButton.setAttribute("href","javascript:;");
}
if(theTooltip)
theButton.setAttribute("title",theTooltip);
if(theText)
theButton.appendChild(document.createTextNode(theText));
if(theClass)
theButton.className = theClass;
else
theButton.className = "button";
if(theId)
theButton.id = theId;
if(attribs){
for(var n in attribs){
e.setAttribute(n,attribs[n]);
}
}
if(theParent)
theParent.appendChild(theButton);
if(theAccessKey)
theButton.setAttribute("accessKey",theAccessKey);
return theButton;
}
config.macros.notes={
cancelWarning: "Are you sure you want to abandon changes to your notes for '%0'?",
editLabel: "edit notes",
editTitle: "double click to edit",
saveLabel: "save notes",
saveTitle: "double click to save",
cancelLabel: "cancel",
heading: "Notes",
suffix: "Notes",
tag: "Notes",
saveNotes: function(ev){
e = ev? ev : window.event;
var theTarget = resolveTarget(e);
if (theTarget.nodeName.toLowerCase() == "textarea")
return false;
var title = story.findContainingTiddler(theTarget).getAttribute("tiddler");
story.setDirty(title,false);
var box = document.getElementById("notesContainer"+title);
var textarea = document.getElementById("notesTextArea"+title);
if(textarea.getAttribute("oldText")!=textarea.value && !hasClass(theTarget,"cancelNotesButton")){
var suffix = box.getAttribute("suffix");
var t = store.getTiddler(title+"-"+suffix);
store.saveTiddler(title+"-"+suffix,title+"-"+suffix,textarea.value,config.options.txtUserName,new Date(),t?t.tags:box.getAttribute("tag"),t?t.fields:{});
}
story.refreshTiddler(title,1,true);
autoSaveChanges(true);
return false;
},
editNotes: function(box,tiddler){
removeChildren(box);
story.setDirty(tiddler,true);
box.title = this.saveTitle;
box.ondblclick = this.saveNotes;
createTiddlyButton(box,this.cancelLabel,this.cancelLabel,this.saveNotes,"cancelNotesButton");
createTiddlyButton(box,this.saveLabel,this.saveLabel,this.saveNotes,"saveNotesButton");
wikify("!!"+box.getAttribute("heading")+"\n",box);
addClass(box,"editor");
var wrapper1 = createTiddlyElement(null,"fieldset",null,"fieldsetFix");
var wrapper2 = createTiddlyElement(wrapper1,"div");
var e = createTiddlyElement(wrapper2,"textarea","notesTextArea"+tiddler);
var v = store.getValue(tiddler+"-"+box.getAttribute("suffix"),"text");
if(!v)
v = config.options.chkPrefillNotes? store.getValue(tiddler,"text"):'';
e.value = v;
e.setAttribute("oldText",v);
var rows = 10;
var lines = v.match(/\n/mg);
var maxLines = Math.max(parseInt(config.options.txtMaxEditRows),5);
if(lines != null && lines.length > rows)
rows = lines.length + 5;
rows = Math.min(rows,maxLines);
e.setAttribute("rows",rows);
box.appendChild(wrapper1);
},
editNotesButtonOnclick: function(e){
var title = story.findContainingTiddler(this).getAttribute("tiddler");
var box = document.getElementById("notesContainer"+title);
config.macros.notes.editNotes(box,title);
return false;
},
ondblclick : function(ev){
e = ev? ev : window.event;
var theTarget = resolveTarget(e);
var title = story.findContainingTiddler(theTarget).getAttribute("tiddler");
var box = document.getElementById("notesContainer"+title);
config.macros.notes.editNotes(box,title);
e.cancelBubble = true;
if(e.stopPropagation) e.stopPropagation();
return false;
},
handler : function(place,macroName,params,wikifier,paramString,tiddler){
params = paramString.parseParams("anon",null,true,false,false);
var heading = getParam(params,"heading",this.heading);
var tag = getParam(params,"tag",this.tag);
var suffix = getParam(params,"suffix",this.suffix);
var box = createTiddlyElement(place,"div","notesContainer"+tiddler.title,"TiddlerNotes",null,{"source":tiddler.title,params:paramString,heading:heading,tag:tag,suffix:suffix});
createTiddlyButton(box,this.editLabel,this.editLabel,this.editNotesButtonOnclick,"editNotesButton");
wikify("!!"+heading+"\n",box);
box.title=this.editTitle;
box.ondblclick = this.ondblclick;
wikify("<<tiddler [["+tiddler.title+"-"+suffix+"]]>>",box);
}
};
Story.prototype.old_notes_closeTiddler = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,unused){
if(story.isDirty(title)) {
if(!confirm(config.macros.notes.cancelWarning.format([title])))
return false;
}
return this.old_notes_closeTiddler.apply(this,arguments);
}
setStylesheet(".TiddlerNotes {\n"+ " background:#eee;\n"+ " border:1px solid #ccc;\n"+ " padding:10px;\n"+ " margin:15px;\n"+ "}\n"+ "\n"+ ".cancelNotesButton,.editNotesButton, .saveNotesButton {\n"+ " float:right;\n"+ " border:1px solid #ccc;\n"+ " padding:2px 5px;\n"+ "}\n"+ "\n"+ ".saveNotesButton{\n"+ " margin-right:0.5em;\n"+ "}\n"+ "\n"+ ".TiddlerNotes.editor textarea{\n"+ " border:1px solid #ccc;\n"+ "}","NotesPluginStyles");
//!END-PLUGIN-CODE
// %/
Translators and commentators sometimes make it sound as if Machiavelli were talking about something altogether different than the tradition, as if this were just an instance in which one word was being used for entirely different ideas. But then Machiavelli's philosophical point would be lost. Machiavelli is taking the traditional concept of virtue as natural human excellence, with all its teleological baggage, and giving it a partially new content. Excellence for a ruler is not the same thing as excellence for a citizen, and excellence for a ruler involves a willingness to engage in what would otherwise be immoral, unjust conduct, and which still may tarnish the ruler's immortal soul, even if it is necessary in the situation for the safety / glory of the patria. It is not the case that all virtues (= excellences) go together and imply one another, as Socrates optimistically believed. New conception of an old concept, not just homonyms.
<<notes>>
<<tag demo>>
This allows notes!
<<notes>>
To include another tiddler's contents inside a tiddler, e.g. here's [[subtabB1]]:
<<tiddler "subtabB1">>
<<tag demo>>
* [[Complete ToDo Tiddler|http://www.giffmex.org/todolisttemplate.html]]
*[[Roadmap and known bugs at Hawksworx.com|http://www.hawksworx.com/playground/TeamTasks/roadmap.html]] last modified byPhilHawkswort on 10 March 2008
*[["Tiddler Parts" plugin|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin]] by [[Udo Borkowski|http://www.abego-software.de/]] (see also [[list of his plugins|http://tiddlywiki.abego-software.de/#Plugins]])
*[[FND's DevPad|http://devpad.tiddlyspot.com/]]
*[[Saq's "Tiddly Learning" blog Lewcid.org|http://lewcid.org/]]
*[[Some useful reference stuff by Jules|http://knighjm.googlepages.com/knightnet-default-tw.html#Reference]] including lists of built-in macros, formatting rules and useful javascript methods for developers.
*[[Repository for BidiX's TiddlyWiki Extensions|http://tiddlywiki.bidix.info/]]
*[[Extension Repository|http://tw.lewcid.org/]] from [[LewCid.org|http://lewcid.org/]]
*[[TiddlyChatter|http://tiddlychatter.tiddlyspot.com/]] at http://tiddlyspot.com/
*[[presentation template|http://lewcid.googlepages.com/presentation_empty_full.html]] ([[see it in action|http://lewcid.googlepages.com/tots.html]])
*[[WebView|http://www.giffmex.org/webviewtwexample.html]] (gotta luv the editor functions here!).
PluginArchives | [[Martin's wiki Martin Budden's plugins and extensions for TiddlyWiki|http://martinswiki.com/]]
External:
*[[TWFaq|http://twfaq.tiddlyspot.com/]] and [[elaborate help|http://tiddlyspot.com/twhelp/]] at [[TiddlySpot.com|http://tiddlyspot.com/]]
*[[CheatSheet (PDF)|http://nothickmanuals.info/lib/exe/fetch.php/cheatsheets:tiddlywiki_cheatsheet.pdf]]
*[[Daniel Baird's UserGuide|http://danielbaird.com/tiddlywikiguides/userguide-sample.html#TiddlyWiki User's Guide]]
*[[TW Resources on TiddlyWiki.org's Wiki|http://www.tiddlywiki.org/wiki/TiddlyWiki_Resources]]
*[[Jim Barr's fully enhanced TW|http://tiddlywikitips.com/]]
*[[TW for the Rest of Us|http://giffmex.org/twfortherestofus.html]]
From [[JeremyRuston's "Getting Started" at TiddlyWiki.com|http://www.tiddlywiki.com/#GettingStarted]]:
----
There is an extensive [[Community]] [[documentation wiki|http://www.tiddlywiki.org/]], including an invaluable [[FAQ|http://www.tiddlywiki.org/wiki/TiddlyWiki_FAQ]]. Other useful guides include:
* Jeremy Wagstaff's [[The Power of Tiddly|http://www.loosewireblog.com/2007/11/the-power-of-ti.html]]
* Dave Gifford's [[TiddlyWiki for the Rest of Us|http://www.giffmex.org/twfortherestofus.html]] and his [[slideshow introduction|http://www.giffmex.org/blog/?p=23]]
* Morris Gray's [[TW Help - TiddlyWiki help file for beginners|http://tiddlyspot.com/twhelp/]]
* Dmitri Popov's [[TiddlyWiki quick reference card|http://nothickmanuals.info/doku.php/cheatsheets]]
* Screencasts from [[JimVentola|http://faculty.massasoit.mass.edu/jventola/videocasts/tidhelp2/tidhelp2.html]] and [[LeonKilat|http://max.limpag.com/2006/09/07/using-a-tiddlywiki-a-video-guide/]].
----
<<tag resources>>
[["Performance Tips"|Tips for speeding up performance on large TiddlyWikis]] and [[Customize your TW experience|For advanced users: Customize your TW experience]], both from [[TW for the Rest of Us|http://giffmex.org/twfortherestofus.html]]
External resources:
*[[Plugin Development|http://tiddlywiki.org/wiki/Plugin_Development]]
*[[Bookmarklets|http://lewcid.org/tiddlywiki-bookmarklets/]]
* [[TiddlyVault index of extensions from Giffmex.org|http://tiddlyvault.tiddlyspot.com/]]
Setting up your own server would require
*internet connection
*[[HTTP server|http://httpd.apache.org]]
*[[PHP4/5|http://php.net]]
*[[MySQL|http://mysql.com]]
''Benefit''
*no cash required apart from your internet connection
*Database is kept private
*No advertising
''Issues''
*Spending time to maintain the server (such as learn to set one up, keep server up to date)
*Require a domain (you can get them free from [[here|http://no-ip.com]]
*Security
*Uptime (if your internet connection is down at home, you wont be able to access it at work)
*Computer switch on all the time (hidden cost in electricity)
see [[Installing on lycos]] for some configuration data
<<tag requirements>>
If you want to renting webspace, you will need access to
*~PHP4/5
*~MySQL
''Benefit''
*Uptime (depending on your provider)
*Saves time from maintaining server
*No advertising
''Issues''
*Database is "not as private" since your provider now have access to it
*Cost a bit of money, but they are relatively cheap nowadays
*Need to get a domain
<<tag requirements>>
See also ChrisCookbook
''NB'': I'm trying to save TiddlyWikiDev on [[Chris' "ServerSideHome" PlayAround|http://peermore.com:8080/recipes/TiddlyWeb/tiddlers.wiki#PlayAround]]
Ripped off from [[Chris' TechnicalOverview|http://peermore.com:8080/recipes/AutoTiddlyWeb/tiddlers.wiki#TiddlyWebTechnicalOverview]]
----
TiddlyWeb is written using version 2.5 of [[Python]].
Its basic architecture is strongly based on [[Joe Gregorio]]'s [[Robaccia]] toy framework, meaning: TiddlyWeb is a [[WSGI]] application that uses [[Selector]] to dispatch a small number of URLs to simple functions in simple modules that satisfy the request.
The TiddlyWeb UrlMap maps URLs to code.
There are three primary entities operating in the TiddlyWeb system:
* [[Recipe]]s
* [[Bag]]s
* [[Tiddler]]s
These are represented in code by very simple classes. Recipe, Bag and Tiddler objects have no methods, only attributes. Other modules use the objects in concert with other modules to perform required actions. These other modules can be divided into sets:
* WebHandlers
* [[Store]]s
* [[Serializer]]s
* [[Control]]
* [[Filter]]s
* [[WSGI Middleware]]
The UrlMap dispatches requests to WebHandlers. The WebHandlers instantiate Recipe, Bag and Tiddler objects and then get them from or put them to [[Store]]s. When the request requires some form of output, a [[Serializer]] is used to transform the object to the required form. A bastardized form of [Content Negotiation] is done to select which Serializer to use.
There are some notes on [[AUTH]] and [[REVISIONS]].
More to come.
----
And //that//, as they say, //is ''that''!//
<<tag history>>
*sigh* I click [[New Journal]] and the one I've been working on all day opens.
Can't have that sorta core dysfunction.
Can't.
~CannotRPTnot.
*sigh*
<<tag journal>>
Posted to [[the TW Dev google group|http://groups.google.com/group/TiddlyWikiDev]] ... I had in mind such as [[The "TiddlyVault" index of extensions|http://tiddlyvault.tiddlyspot.com/"]] and [[TiddlyWiki in Action|http://giffmex.tiddlyspot.com/]]
----
As you can see by http://wiki.osmosoft.com/alpha/pardelib#Resources and my Journals there I've been spidering quite a bit.
When I come across something like the editor function in http://www.giffmex.org/webviewtwexample.html the fact that Import is of limited scope really hammers me in the head.
So thinking, I pondered how we might "sync" plugins / templates etc.
Of course ginsu / cook / recipes came to mind.
Anecdotally, ExtJS allows the download of a customized build.
With that in mind an RFE came to mind.
A repository where ~TWs could be built from scratch using the groups aggregated resources. (Have any of you come across "Puppet"? "Make, on steroids" is how one wag described it.)
For e.g. I uploade the empty.html's that I've collected.
Those go into a directory and get ginsu'd.
A menu is generated.
I select from that collection and the chimera is produced, for me to download.
Heck, I can imagine an Import that would allow me to drag in Tiddlers from whatever ~TWs I've loaded!
Apologies if this is madly impractical.
cheers
[[--bentrem|http://twitter.com/bentrem/]]
----
<<tag blurt>>
From [[ChrisDent/experimental/TiddlyWeb/COOKBOOK|http://trac.tiddlywiki.org/browser/Trunk/contributors/ChrisDent/experimental/TiddlyWeb/COOKBOOK]]
(Thanks to [[Jeremy Ruston for his reply to my "CordonBlue" suggestion in google group|http://groups.google.com/group/TiddlyWikiDev/browse_thread/thread/6562d68583b31eb7]].)
----
>Document a COOKBOOK for getting starting with TiddlyWeb. A fairly long and involved tutorial to cover the basics of making things go.
>This was just rolled out, and is not my area of expertise so I would very much welcome tweaks from others.
----
//''NB''//: Disappointment: trying a use case, I a) imported a plugin (~RearrangeTiddlersPlugin) to my local file, b) uploaded that to [[my site|http://bentrem.sycks.net/tw/pardelib.html]], then c) came here and tried to import from my local ... which would have been nice. No joy. Meh.
>A script from "http://wiki.osmosoft.com" was denied UniversalBrowserRead privileges.
>[Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXMLHttpRequest.setRequestHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: http://wiki.osmosoft.com/alpha/pardelib :: doHttp :: line 6646" data: no]
When I tried to import from [[my site|http://bentrem.sycks.net/tw/pardelib.html]] I was again blocked, with a different error:
>"A script from "http://wiki.osmosoft.com" was denied UniversalBrowserRead privileges."
`cough`
I just tried to import from http://www.tiddlytools.com ... same problem.
So: ~ParDelib here is now out of sync with ~ParDelib local and at bentrem.sycks.net, which both have the Rearrange plugin.
And I can only see this getting worse.
Dang.
----
Ooooh, just gotta get the Plugin that gives Tiddlers a "collapse" function, see [[Deferential Geometry TW|http://deferentialgeometry.org/]]
That and getting the editor functions from [[WebView|http://www.giffmex.org/webviewtwexample.html]] ... I need a ~ToDo list! Break out the GTD functionality.
I just worked through [[Getting started with UploadPlugin|http://www.tiddlywiki.org/wiki/Getting_started_with_UploadPlugin]] and created a copy of this locally and uploaded to [[bentrem.sycks.net/tw/pardelib.html|http://bentrem.sycks.net/tw/pardelib.html]].
<<tag journal>>
I'm using osmosoft.com/alpha/pardelib as my test bed.
And, by way of introduction:
* http://bentrem.sycks.net
* http://groundplane.wordpress.com
* http://gnodal.livejournal.com
* http://twitter.com/bentrem/
<html><div align="center">
<iframe border="0" style="border:none;padding:0;margin:0;" width="320" height="400" src="http://gfreecomment.appspot.com/freecomment/541?url=' + location.href + '"></iframe></div></html>
This worked after stripping down the original cope, converting it from a document.write script to a naked <iframe>:
> <script type="text/javascript">
>document.write('<iframe border="0" style="border:none;padding:0;margin:0;" width="210" height="400" src="http://gfreecomment.appspot.com/freecomment/541?url=' + location.href + '">iframe</iframe>');
></script>
This site is a ~TiddlyWiki!
~TiddlyWiki is a wiki packaged within a single html file, complete with all the content, the editing and saving functionality, search and tagging capabilities and much more. It can run locally from your hard drive (so it's great for taking notes or organising personal information) or on a server.
~TiddlyWiki is a single web page which contains not just content, but also the functionality needed to edit and save that content. Being a single web page makes it very portable, as it can easily be emailed or handed to somebody on a USB stick. It can also be accessed via the web in a conventional sense - as you likely did for this site.
~TiddlyWiki is very extensible; there are over 400 plugins developed by the ~TiddlyWiki community.
You can learn more about TiddlyWiki here:
Official ~TiddlyWiki site: http://www.tiddlywiki.com
Main ~TiddlyWiki developers site: http://www.tiddlywiki.org
~TiddlyWiki Google Group: http://groups.google.com/group/TiddlyWiki
~TiddlyWiki Developers Google Group: http://groups.google.com/group/TiddlyWikiDev
[[irc://irc.freenode.net/tiddlywiki|irc://irc.freenode.net/tiddlywiki]]
!!!!Welcome to ccTiddly 1.6 alpha!
This site is created and presented with ccTiddlyWiki ... and ''ccTiddly'' is a server-side implementation of TiddlyWiki created by [[Osmosoft]] to provide a centralised location for teams looking for a collaboration platform.
You can use this tool to create multiple editions of ~TiddlyWiki (we call each edition a 'workspace'), which can be seen and edited by whomever you wish. If you don't already have an account please [[register|Register]] for one. (Note that user registration is a new feature and still requires some work.)
If you have any problems with this deployment please contact simon@osmosoft.com. Feedback is welcomed!
My "CordonBlue" suggestion is getting [[some replies on Dev group|http://groups.google.com/group/TiddlyWikiDev/browse_thread/thread/6562d68583b31eb7?hl=en]]
----
Well ... just started playing with stuff from bidix.com ... saved a local version and found it very attractive.
Proceeded to use the UpLoad tiddler and *blink* found it configured to pardelib.html ... it wudda blown away my previous work.
So I reconfigured it to bidix.com and [[succeeded with the upload|http://bentrem.sycks.net/tw/bidix.html]], which was nice. But then I peeked the upload config for ParDelib and, ayup, it had been changed to bidix.html.
So ... I mean, really ... my whole machine has been taken over by a single file?!
Sorry folks, that's just wrong-headed. Fine, fine, use cookies ... but cookie for bidix.html should be distinct from pardelib.html ... I mean it: really.
----
Gotta keep an eye on these:
* [[Simon Baird's Monkey Pirate TW blog|http://monkeypiratetiddlywiki.blogspot.com/]]
* Lots of posts to grapple with on [[Saq's "Tiddly Learning" blog Lewcid.org|http://lewcid.org/]]
And, incidentally: the [["It's All Text" extension for Firefox|https://addons.mozilla.org/fr/firefox/addon/4125]] (created by [[Dr. What|http://docwhat.gerf.org]]. I gotta say I'm getting more than a little fed up with people who maintain anonymity. ''Get over yourselves!'')... this is called up by the "Externalize" tiddler some TWs are using.
----
Of note: [[VisualTW|http://visualtw.ouvaton.org/VisualTW.html]] has a very interesting host: http://ouvaton.org ... most of it (all?) is in French (which don't bother me a bit), and a good deal of it relates to [[the cooperative movement over there|http://www.entreprises.coop/]] ... very interesting!
<<tag journal>>
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Version|1.6.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements 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.
!!!!!Usage
<<<
When installed, this plugin adds new wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be treated as embedded javascript and executed each time the tiddler is rendered.
''Deferred execution from an 'onClick' link''
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
''External script source files:''
You can also load javascript 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.
''Display script source in tiddler output''
By including the keyword parameter "show", in the initial {{{<script>}}} marker, the plugin will include the script source code in the output that it displays in the tiddler.
''Defining javascript functions and libraries:''
Although the external javascript file is loaded while the tiddler content is being rendered, any functions it defines will not be available for use until //after// the rendering has been completed. Thus, you cannot load a library and //immediately// use it's functions within the same tiddler. However, once that tiddler has been loaded, the library functions can be freely used in any tiddler (even the one in which it was initially loaded).
To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that will be rendered as soon as your TiddlyWiki document is opened. For example, you could put your {{{<script src="..."></script>}}} syntax into a tiddler called LoadScripts, and then add {{{<<tiddler LoadScripts>>}}} in your MainMenu tiddler.
Since the MainMenu is always rendered immediately upon opening your document, the library will always be loaded before any other tiddlers that rely upon the functions it defines. Loading an external javascript library does not produce any direct output in the tiddler, so these definitions should have no impact on the appearance of your MainMenu.
''Creating dynamic tiddler content''
An important difference between this implementation of embedded 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() 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 completely replaces the entire ~TiddlyWiki document in your browser window.
* To allow these scripts to work unmodified, the plugin automatically converts all occurences of document.write() so that the output is inserted into the tiddler content instead of replacing the entire ~TiddlyWiki document.
If your script does not use document.write() to create dynamically embedded content within a tiddler, your javascript can, as an alternative, explicitly return a text value that the plugin can then pass through the wikify() rendering engine to insert into the tiddler display. For example, using {{{return "thistext"}}} will produce the same output as {{{document.write("thistext")}}}.
//Note: your script code is automatically 'wrapped' 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.//
''Accessing the ~TiddlyWiki DOM''
The plugin provides one pre-defined variable, 'place', that is passed in to your javascript code so that it can have direct access to the containing DOM element into which the tiddler output is currently being rendered.
Access to this DOM element allows you to create scripts that can:
* vary their actions based upon the specific location in which they are embedded
* access 'tiddler-relative' information (use findContainingTiddler(place))
* perform direct DOM manipulations (when returning wikified text is not enough)
<<<
!!!!!Examples
<<<
an "alert" message box:
><script show>
alert('InlineJavascriptPlugin: this is a demonstration message');
</script>
dynamic output:
><script show>
return (new Date()).toString();
</script>
wikified dynamic output:
><script show>
return "link to current user: [["+config.options.txtUserName+"]]";
</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).id.substr(7);
return title+" is using "+store.getTiddlerText(title).length+" bytes";
</script>
creating an 'onclick' button/link that runs a script:
><script label="click here" title="clicking this link will show an 'alert' box" show>
if (!window.story) window.story=window;
alert("Hello World!\nlinktext='"+place.firstChild.data+"'\ntiddler='"+story.findContainingTiddler(place).id.substr(7)+"'");
</script>
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function demo() { alert('this output is from demo(), defined in demo.js') } }}}
>>{{{alert('InlineJavascriptPlugin: demo.js has been loaded'); }}}
><script src="demo.js" show>
return "loading demo.js..."
</script>
><script label="click to execute demo() function" show>
demo()
</script>
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''InlineJavascriptPlugin'' (tagged with <<tag systemConfig>>)
<<<
!!!!!Revision History
<<<
''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
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]
<<<
!!!!!Code
***/
//{{{
version.extensions.inlineJavascript= {major: 1, minor: 6, revision: 0, date: new Date(2007,2,19)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\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) {
if (lookaheadMatch[1]) { // load a script library
// make script tag, set src, add to body to execute, then remove for cleanup
var script = document.createElement("script"); script.src = lookaheadMatch[1];
document.body.appendChild(script); document.body.removeChild(script);
}
if (lookaheadMatch[5]) { // there is script code
if (lookaheadMatch[4]) // show inline script code in tiddler output
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (lookaheadMatch[2]) { // create a link to an 'onclick' script
// add a link, define click handler, save code in link (pass 'place'), set link attributes
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",lookaheadMatch[2]);
link.onclick=function(){try{return(eval(this.code))}catch(e){alert(e.description?e.description:e.toString())}}
link.code="function _out(place){"+lookaheadMatch[5]+"\n};_out(this);"
link.setAttribute("title",lookaheadMatch[3]?lookaheadMatch[3]:"");
link.setAttribute("href","javascript:;");
link.style.cursor="pointer";
}
else { // run inline script code
var code="function _out(place){"+lookaheadMatch[5]+"\n};_out(w.output);"
code=code.replace(/document.write\(/gi,'place.innerHTML+=(');
try { var out = eval(code); } 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;
}
}
} )
//}}}
Say hello; leave me a note!
<html><div align="center">
<iframe border="0" style="border:none;padding:0;margin:0;" width="380" height="400" src="http://gfreecomment.appspot.com/freecomment/541?url=' + location.href + '">iframe</iframe></html>
<<section ChangedBGsIn2Plugins I switched bg color in ~DropDown and Accordion from #0066aa to #3278FC
>>
<<section MenuAccordions Trying to work DropDownDemo into MainMenu, but here's a subtle downside:
as is, my conventional [[MainMenu|MenuMenuBak]] uses inclusions ... when I create a new journal, I don't edit MainMenu, I edit [[Journals]] ... and likewise with [[Blurts]]. MainMenu doesn't change, and I end up with nice stand-alone slabs of links.
If I use drop-downs, I need to edit MainMenu, and lost those nice slabs.
>>
----
I just brought in SectionMacro from [[SabWiki (by GiffMex, at rsabine.com/|http://rsabine.com/]]
I wanted this here to work in the Section: {{{<<tiddler [[GFreeComment]]>>}}}
<<section SnagsWithSectionMacro I had hoped this section would allow me to include another Plugin, i.e. the code immediately above, but no such luck ... I can't get the functionality, I can't even include that quote code section ... bummer.>>
A near equivalent: AnonGreets now uses this type of accordion:
* Show Code
**{{myclass{
{{{<<tiddler [[GFreeComment]]>>}}}
}}}
<<accordion>>Which works well enough, but there seems no way to close it!
<<section TableFormats [[Customize your TW experience|For advanced users: Customize your TW experience]], from [[TW for the Rest of Us|http://giffmex.org/twfortherestofus.html]] ... it uses an interesting table layout; the "invisible" part isn't quite working, and --I can't get align:left and vertical-align:top; to work. So maybe FormatTables will help.-- //ayup, it did!//
!!!//haaaahaha// ... the spaces caused things to a) right align, and then b) screw up totally. heh!!!
>>
<<section GFreeCommentsWorking I just got [[GFreeComment|GFreeCommentInfo]] working and included it in tiddlers as [[GFreeComment]]. see http://gfreecomment.appspot.com/
>>
<<section ReFactorRightSideBar Just added RearrangeTiddlersPlugin ...
... and just now hid Timeline and the other tabs behind a slider, cutting the contents of SideBarTabs to SideBarContents
>>
/***
|Name|RearrangeTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#RearrangeTiddlersPlugin|
|Version|0.0.0|
|Author|Joe Raii|
|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|Story.prototype.refreshTiddler|
|Description|drag tiddlers by title to re-order story column display|
adapted from: http://www.cs.utexas.edu/~joeraii/dragn/#Draggable
changes by ELS:
* hijack refreshTiddler() instead of overridding createTiddler()
* find title element by className instead of elementID
* set cursor style via code instead of stylesheet
* set tooltip help text
* set tiddler "position:relative" when starting drag event, restore saved value when drag ends
* update 2006.08.07: use getElementsByTagName("*") to find title element, even when it is 'buried' deep in tiddler DOM elements (due to custom template usage)
* update 2007.03.01: use apply() to invoke hijacked core function
* update 2008.01.13: only hijack core function once. (allows for dynamic loading of plugin via bookmarklet)
***/
//{{{
if (Story.prototype.rearrangeTiddlersHijack_refreshTiddler===undefined) {
Story.prototype.rearrangeTiddlersHijack_refreshTiddler = Story.prototype.refreshTiddler;
Story.prototype.refreshTiddler = function(title,template)
{
this.rearrangeTiddlersHijack_refreshTiddler.apply(this,arguments);
var theTiddler = document.getElementById(this.idPrefix + title); if (!theTiddler) return;
var theHandle;
var children=theTiddler.getElementsByTagName("*");
for (var i=0; i<children.length; i++) if (hasClass(children[i],"title")) { theHandle=children[i]; break; }
if (!theHandle) return theTiddler;
Drag.init(theHandle, theTiddler, 0, 0, null, null);
theHandle.style.cursor="move";
theHandle.title="drag title to re-arrange tiddlers"
theTiddler.onDrag = function(x,y,myElem) {
if (this.style.position!="relative")
{ this.savedstyle=this.style.position; this.style.position="relative"; }
y = myElem.offsetTop;
var next = myElem.nextSibling;
var prev = myElem.previousSibling;
if (next && y + myElem.offsetHeight > next.offsetTop + next.offsetHeight/2) {
myElem.parentNode.removeChild(myElem);
next.parentNode.insertBefore(myElem, next.nextSibling);//elems[pos+1]);
myElem.style["top"] = -next.offsetHeight/2+"px";
}
if (prev && y < prev.offsetTop + prev.offsetHeight/2) {
myElem.parentNode.removeChild(myElem);
prev.parentNode.insertBefore(myElem, prev);
myElem.style["top"] = prev.offsetHeight/2+"px";
}
};
theTiddler.onDragEnd = function(x,y,myElem) {
myElem.style["top"] = "0px";
if (this.savedstyle!=undefined)
this.style.position=this.savedstyle;
}
return theTiddler;
}
}
/**************************************************
* dom-drag.js
* 09.25.2001
* www.youngpup.net
**************************************************
* 10.28.2001 - fixed minor bug where events
* sometimes fired off the handle, not the root.
**************************************************/
var Drag = {
obj:null,
init:
function(o, oRoot, minX, maxX, minY, maxY) {
o.onmousedown = Drag.start;
o.root = oRoot && oRoot != null ? oRoot : o ;
if (isNaN(parseInt(o.root.style.left))) o.root.style.left="0px";
if (isNaN(parseInt(o.root.style.top))) o.root.style.top="0px";
o.minX = typeof minX != 'undefined' ? minX : null;
o.minY = typeof minY != 'undefined' ? minY : null;
o.maxX = typeof maxX != 'undefined' ? maxX : null;
o.maxY = typeof maxY != 'undefined' ? maxY : null;
o.root.onDragStart = new Function();
o.root.onDragEnd = new Function();
o.root.onDrag = new Function();
},
start:
function(e) {
var o = Drag.obj = this;
e = Drag.fixE(e);
var y = parseInt(o.root.style.top);
var x = parseInt(o.root.style.left);
o.root.onDragStart(x, y, Drag.obj.root);
o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;
if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
document.onmousemove = Drag.drag;
document.onmouseup = Drag.end;
Drag.obj.root.style["z-index"] = "10";
return false;
},
drag:
function(e) {
e = Drag.fixE(e);
var o = Drag.obj;
var ey = e.clientY;
var ex = e.clientX;
var y = parseInt(o.root.style.top);
var x = parseInt(o.root.style.left);
var nx, ny;
if (o.minX != null) ex = Math.max(ex, o.minMouseX);
if (o.maxX != null) ex = Math.min(ex, o.maxMouseX);
if (o.minY != null) ey = Math.max(ey, o.minMouseY);
if (o.maxY != null) ey = Math.min(ey, o.maxMouseY);
nx = x + (ex - o.lastMouseX);
ny = y + (ey - o.lastMouseY);
Drag.obj.root.style["left"] = nx + "px";
Drag.obj.root.style["top"] = ny + "px";
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;
Drag.obj.root.onDrag(nx, ny, Drag.obj.root);
return false;
},
end:
function() {
document.onmousemove = null;
document.onmouseup = null;
Drag.obj.root.style["z-index"] = "0";
Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style["left"]), parseInt(Drag.obj.root.style["top"]), Drag.obj.root);
Drag.obj = null;
},
fixE:
function(e) {
if (typeof e == 'undefined') e = window.event;
if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
return e;
}
};
//}}}
* http://groups.google.com/group/TiddlyWikiDev is the [[google groups page|http://groups.google.com/group/TiddlyWikiDev]]
~BenTrem's list of ~TiddlyWiki Resources
*[[Main TiddlyWiki site|http://www.tiddlywiki.com]] and [[Developers' site|http://www.tiddlywiki.org/wiki/TiddlyWeb]]
*[[TWFaq at TiddlySpot|http://twfaq.tiddlyspot.com/]]
*[[Julian Knight's references|http://knighjm.googlepages.com/knightnet-default-tw.html]]
*[[Google Group|http://groups.google.com/group/TiddlyWiki]]
*[[Developers Google Group|http://groups.google.com/group/TiddlyWikiDev]]
*[[Write-up at OsmoSoft|http://osmosoft.com/#TiddlyWiki]]
ripped from [[Giffmex.org/twfortherestofus.html|http://www.giffmex.org/twfortherestofus.html#[[Tips for speeding up performance on large TiddlyWikis]]]]
*''Disable the animations.'' It may be cute to have tiddlers open with cool animation, but the animation slows performance way down. Open the OptionsPanel and uncheck ~EnableAnimations.
*''Save less often.'' Uncheck 'Autosave' and 'Save backups', and save manually every few minutes instead of saving every single change.
*''Hide the growing tabbed lists in your SideBarTabs.'' Every time you create a new tiddler, TabAll and TabTimeline have to refresh to add the new tiddler's title. As the list of tiddlers gets longer, these tabs take longer to refresh, slowing down your ~TiddlyWiki. There are three ways I know of to hide these lists:
##The easiest way is to click on the More tab. The lists in More don't grow like the other lists. This should be a good enough solution for most users.
##You can use the ToggleRightSidebar plugin to hide the entire right hand sidebar of your ~TiddlyWiki screen. This plugin happens to be included in this tutorial.
##I don't necessarily recommend the following for newer users, but to remove the right hand sidebar tabs from view altogether, open PageTemplate and delete the following:
<!--{{{-->
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<!--}}}-->
*''Michael Cimino offered this suggestion by e-mail:''
"...(1) add the following to the end of SidebarOptions: {{{<<slider chkSliderContents [[TabContents]] 'contents »' 'contents'>>}}}
(2) cut out the text from SidebarTabs and save it, leaving it blank.
(3) create a new tiddler TabContents and paste the text that used to be in SidebarTabs, which should be:
{{{<<tabs txtMainTab "Timeline" "Timeline" TabTimeline "All" "All tiddlers" TabAll "Tags" "All tags" TabTags "More" "More lists" TabMore>>}}}
Now, you can collapse that area of the Sidebar whenever you wish, and its state will be saved in a cookie! I hope this helps!"
<<tabs txtMainTab "Timeline" "Timeline" TabTimeline "All" "All tiddlers" TabAll "Tags" "All tags" TabTags "More" "More lists" TabMore>>
/***
|Name|ToDoPlugin|
|Source|http://kronenpj.tiddlyspot.com/#ToDoPlugin|
|Version|0.0.5|
|Author|Paul Kronenwetter <kronenpj@gmail.com>|
|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|InlineJavascriptPlugin,CheckboxPlugin|
|Overrides||
|Description|Displays to do information from data elements in the calling tiddler.|
!!!!!Revisions
<<<
2008.06.30 [0.0.5] Moved refresh code to improve performance for deleting tasks near the top of a long list.
2008.06.30 [0.0.4] Changed all field names to be prefixed with 'tdp' to hopefully avoid collisions. Unfortunately, this again breaks existing tiddlers. Changed the move up/down symbols to a better looking symbol. Added CSS to remove the table borders. Thanks to Tobias for suggesting all these.
2008.06.27 [0.0.3] Converted to using fields rather than DataTiddlerPlugin. Incorporated and ported Tobias's delete task code. Slightly reduced duplication of code by adding commonly used routines to variables, as Tobias did in his submitted code. Globalized swap and delete task routines. Fixed bug where the checkboxes didn't follow the task names when being reordered be eliminating use of DataTiddlerPlugin.
2008.06.26 [0.0.2] Corrected bug found by Morris Gray related to single and double quotes truncating task entries. Adopted Tobias Beer's contribution for a simple sorting mechanism. Reduced the code slightly by extracting the sorting code into a separate string, but it's still replicated in each button within the script tags.
2008.06.23 [0.0.1] initial release
<<<
!!!!!Usage
Place {{{<<displayToDoList>>}}} into a tiddler. Use the "Add task" button to add tasks. Edit individual tasks using the text fields. Move tasks up or down using the links on the left.
!!!!!Known Bugs
* None at the moment.
!!!!!Code
***/
//{{{
version.extensions.displayToDoList = {major: 0, minor: 0, revision: 5, date: new Date(2008,6,30)};
config.macros.displayToDoList = {
handler:
function(place) {
if (!window.story) window.story=window;
var wrapper = createTiddlyElement(place, "span");
var title=story.findContainingTiddler(place).id.substr(7);
var myTiddler = store.getTiddler(title);
var titleURI = encodeURIComponent(title);
var text = "";
var dataCount = parseInt(myTiddler.fields['tdpcount']);
var arrSwapJs = ' arrSwap = new Array("tdptask","tdpdone");';
var headJs = 'var myTiddler = store.getTiddler(title);';
headJs += 'var count = parseInt(myTiddler.fields[\'tdpcount\']) || 0;';
var refreshJs = ' store.setDirty(title, true);';
refreshJs += ' story.refreshTiddler(title,null,true);';
text += '<html><style id="ToDoPlugin" type="text/css">';
text += '.viewer .noBorder,.viewer .noBorder td,.viewer .noBorder th,.viewer .noBorder tr{border:0} ';
text += '</style></html>';
text += '<script label="Add task">';
text += 'var title=story.findContainingTiddler(place).id.substr(7);';
text += headJs;
text += ' myTiddler.fields[\'tdptask\' + count] = "Task";';
text += ' myTiddler.fields[\'tdpdone\' + count] = false;';
text += ' myTiddler.fields[\'tdpcount\'] = String(parseInt(count+1));';
text += refreshJs;
text += '</script>';
text += '<script>';
text += 'window.TDPSwapTask = function(title,item, pos) {';
text += headJs;
text += arrSwapJs;
text += ' var i = parseInt(item);';
text += ' for (v=0; v<arrSwap.length; v++) {';
text += ' var sVar = arrSwap[v];';
text += ' var tmpVal = myTiddler.fields[sVar+i];';
text += ' myTiddler.fields[sVar+i] = myTiddler.fields[sVar+ String(parseInt(i+pos))];';
text += ' myTiddler.fields[sVar+ String(parseInt(i+pos))] = tmpVal;';
text += ' }';
text += '};';
text += '</script>';
text += '<script>';
text += 'window.TDPDeleteTask = function(title,item) {';
text += headJs;
text += arrSwapJs;
text += ' var oneFewer = String(parseInt(count-1));';
text += ' var i = parseInt(item);';
text += ' for (var v=i+1;v<count;v++) TDPSwapTask(title,v,-1);';
text += ' myTiddler.fields["tdpcount"] = oneFewer;';
text += ' for (v=0; v<arrSwap.length; v++) ';
text += ' delete myTiddler.fields[arrSwap[v]+oneFewer];';
text += refreshJs;
text += '};';
text += '</script>';
for (var i = 0; i < dataCount ; i++){
text += "\n|noBorder|k\n";
text += '|<script label="\'\X\'\" title="delete task">';
text += 'TDPDeleteTask("' + title + '",' + i + ');';
text += '</script>';
text += "|[_(tdpdone" + i + "@)]|";
// Create the onchange script. This is kinda nasty, but it works.
// Also kinda nasty is the HTML ID assigned to the input element, to be sure it's unique. "tF{TiddlerName}{count}"
var onc='var t=store.getTiddler('' + title + ''); t.fields['tdptask' + i + ''] = ';
onc += 'document.getElementById('tF' + titleURI + i + '').value.replace(/'/g,'\\''); ';
onc += 'store.setDirty('' + title + '', true);';
text += " <html><input type=text size=60 id=tF" + titleURI + i + " onchange='" + onc + "'";
text += " value='" + String(myTiddler.fields['tdptask' + i]).replace(/'/,''');
text += "'></input></html>|";
if (i<dataCount-1) {
text += '<script label="v" title="move task down">';
text += 'var title = \'' + title + '\';';
text += 'TDPSwapTask(title,' + i + ',+1);';
text += refreshJs;
text += '</script>';
}
text += '|';
if (i>0) {
text += '<script label="^" title="move task up">';
text += 'var title = \'' + title + '\';';
text += 'TDPSwapTask(title,' + i + ',-1);';
text += refreshJs;
text += '</script>';
}
text += '|';
}
wikify(text, wrapper, null);
}
};
//}}}
{{invisibletable{
|width:25em;align:left;vertical-align:top;Okay, so you know how to use ~TiddlyWiki, but now you want more. You want to change the color or layout. You want to add features to it. As the subtitle says, this is an entry-level introduction, so I am not going to show you how to do every possible thing you can do with ~TiddlyWiki. I probably don't know half of what can be done. Advanced documentation such as that found at http://www.tiddlywiki.org/wiki and http://tiddlyspot.com/twhelp/ can hopefully expand your horizons. What I will tell you is that there is a LOT more you can do with ~TiddlyWiki if you are interested and determined enough.|Here are a few ideas to get you started.<br><br>[[Advanced ideas for tags]]<br><br>[[More information on tables]]<br><br>[[Colors, images, gradients, stylesheets and other visuals]]<br><br>[[Changing the page layout]]<br><br>[[More with macros]]<br><br>[[A plug for Plugins]]<br><br>[[TiddlyVault collection of plugins and macros|TiddlyVault: your source for macros, plugins and themes]]<br><br>[[How to create new tiddlers based on a template tiddler]]<br><br>[[Create forms with editable fields]]<br><br>[[Access files, folders, etc from within TiddlyWiki]]<br><br>[[TiddlySnip Firefox addon]]|
}}}
I want to thank all the fine people at the Google group for ~TiddlyWiki. If it weren't for them, I wouldn't ever have been able to do these things, let alone explain them to you. It's rare to find such a helpful group of people available every day with same day answers. They are another reason ~TiddlyWiki is so great.
!This is the formatting:
{{{|!Table header|!Column Two|}}}
{{{|>| colspan |}}}
{{{| rowspan |left aligned|}}}
{{{|~| right aligned|}}}
{{{|bgcolor(#DC1A1A):colored| centered |}}}
{{{||*lists<br>*within<br>*tables<br><br>and double-spaced too|}}}
{{{|caption|c}}}
!This is the result:
|!Table header|!Column Two|
|>| colspan |
| rowspan |left aligned|
|~| right aligned|
|bgcolor(#DC1A1A):colored| centered |
||*lists<br>*within<br>*tables<br><br>and double-spaced too|
|caption|c
/***
|''Name:''|~SectionMacro|
|''Version:''|0.9.4 (20-Apr-2007)|
|''Author:''|[[Jack]]|
|''Type:''|Macro|
!Description
Allows you to create collapsable sections just like the slider macro but without needing to create new tiddlers for these sections.
!Usage
{{{<<section Title Tiddler Text goes here...
and can be multi-
line and include {${${monospace text}$}$}.
>>}}}
<<section Title Tiddler Text goes here...
and can be multi-
line and include {${${monospace text}$}$}.
>>
!Revision History
* Original by [[Jack]] 0.9
* Nested sliders and cookie persistence 0.9.1
* Removed crappy cookie persistance 0.9.2
* Bug-fix with quoted 2st parameter (thanks M. Macolio) 0.9.3
* Bug-fix with monospace text (thanks M. Macolio) 0.9.4
!Code
***/
//{{{
version.extensions.section = {major: 0, minor: 9, revision: 4, date: new Date("Apr 20, 2007")};
config.macros.section = {count:0,display:'none'};
config.macros.section.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
this.slider(place,"chkSection" + this.count++,paramString.substr(params[0].length+(paramString.substr(params[0].length+1,1).match(/['"]/)?2:1)).replace(/\$\>/g, '>').replace(/}\$}\$}/, '}}}').replace(/{\${\${/, '{{{'),params[0], "tooltip");
}
config.macros.section.slider = function(place,cookie,text,title,tooltips) {
var btn = createTiddlyButton(place,title,tooltips,config.macros.slider.onClickSlider,"tiddlyLink tiddlyLinkExisting");
var panel = createTiddlyElement(place,"div",null,"timelineSliderPanel",null);
panel.setAttribute("cookie",cookie);
panel.style.display = config.options[cookie] ? "block" : "none";
panel.style.display=this.display;
if(text) wikify(text,panel);
};
//}}}
ChrisDentSez
----
<<slider chkSliderOptionsPanel Blurts 'Blurts »' 'A list of blurts'>>
<<slider chkSliderOptionsPanel Journals 'Journals »' 'A list of journals'>>
----
*[[Customization]]
*GettingStarted
goto [[Resources|Resources]]
----
*AboutMe
[[Comment!|GFreeComment]]
[[SaveA)s pardelibTW.html|http://wiki.osmosoft.com/alpha/pardelib]]
<<tag bak>>
/***
|''Name:''|DropDownMenuPlugin|
|''Description:''|Create dropdown menus from unordered lists|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#DropDownMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|11/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|
!!Usage:
* create a two-level unordered list using wiki syntax, and place {{{<<dropMenu>>}}} on the line after it.
* to create a vertical menu use {{{<<dropMenu vertical>>}}} instead.
* to assign custom classes to the list, just pass them as parameters to the macro {{{<<dropMenu className1 className2 className3>>}}}
!!Features:
*Supports just a single level of drop-downs, as anything more usually provides a poor experience for the user.
* Very light weight, about 1.5kb of JavaScript and 4kb of CSS.
* Comes with two built in css 'themes', the default horizontal and vertical.
!!Customizing:
* to customize the appearance of the menu's, you can either add a custom class as described above or, you can edit the CSS via the StyleSheetDropDownMenu shadow tiddler.
!!Examples:
* [[DropDownMenuDemo]]
***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.dropMenu={
dropdownchar: "\u25bc",
handler : function(place,macroName,params,wikifier,paramString,tiddler){
list = findRelated(place.lastChild,"UL","tagName","previousSibling");
if (!list)
return;
addClass(list,"suckerfish");
if (params.length){
addClass(list,paramString);
}
this.fixLinks(list);
},
fixLinks : function(el){
var els = el.getElementsByTagName("li");
for(var i = 0; i < els.length; i++) {
if(els[i].getElementsByTagName("ul").length>0){
var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
if(!link){
var ih = els[i].firstChild.data;
els[i].removeChild(els[i].firstChild);
var d = createTiddlyElement(null,"a",null,null,ih+this.dropdownchar,{href:"javascript:;"});
els[i].insertBefore(d,els[i].firstChild);
}
else{
link.firstChild.data = link.firstChild.data + this.dropdownchar;
removeClass(link,"tiddlyLinkNonExisting");
}
}
els[i].onmouseover = function() {
addClass(this, "sfhover");
};
els[i].onmouseout = function() {
removeClass(this, "sfhover");
};
}
}
};
config.shadowTiddlers["StyleSheetDropDownMenuPlugin"] =
"/*{{{*/\n"+
"/***** LAYOUT STYLES - DO NOT EDIT! *****/\n"+
"ul.suckerfish, ul.suckerfish ul {\n"+
" margin: 0;\n"+
" padding: 0;\n"+
" list-style: none;\n"+
" line-height:1.4em;\n"+
"}\n\n"+
"ul.suckerfish li {\n"+
" display: inline-block; \n"+
" display: block;\n"+
" float: left; \n"+
"}\n\n"+
"ul.suckerfish li ul {\n"+
" position: absolute;\n"+
" left: -999em;\n"+
"}\n\n"+
"ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {\n"+
" left: auto;\n"+
"}\n\n"+
"ul.suckerfish ul li {\n"+
" float: none;\n"+
" border-right: 0;\n"+
" border-left:0;\n"+
"}\n\n"+
"ul.suckerfish a, ul.suckerfish a:hover {\n"+
" display: block;\n"+
"}\n\n"+
"ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}\n"+
"/**** END LAYOUT STYLES *****/\n"+
"\n\n"+
"/**** COLORS AND APPEARANCE - DEFAULT *****/\n"+
"ul.suckerfish li a {\n"+
" padding: 0.5em 1.5em;\n"+
" color: #FFF;\n"+
" background: #3278FC;\n"+
" border-bottom: 0;\n"+
" font-weight:bold;\n"+
"}\n\n"+
"ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{\n"+
" background: #00558F;\n"+
"}\n\n"+
"ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{\n"+
" color: #000;\n"+
" background: #eff3fa;\n"+
" border-top:1px solid #FFF;\n"+
"}\n\n"+
"ul.suckerfish ul li a:hover {\n"+
" background: #e0e8f5;\n"+
"}\n\n"+
"ul.suckerfish li a{\n"+
" width:9em;\n"+
"}\n\n"+
"ul.suckerfish ul li a, ul.suckerfish ul li a:hover{\n"+
" display:inline-block;\n"+
" width:9em;\n"+
"}\n\n"+
"ul.suckerfish li {\n"+
" border-left: 1px solid #00558F;\n"+
"}\n"+
"/***** END COLORS AND APPEARANCE - DEFAULT *****/\n"+
"\n\n"+
"/***** LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
"ul.suckerfish.vertical li{\n"+
" width:10em;\n"+
" border-left: 0px solid #00558f;\n"+
"}\n\n"+
"ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {\n"+
" border-left: 0.8em solid #00558f;\n"+
"}\n\n"+
"ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a, ul.suckerfish.vertical li.sfhover a:hover{\n"+
" width:8em;\n"+
"}\n\n"+
"ul.suckerfish.vertical {\n"+
" width:10em; text-align:left;\n"+
" float:left;\n"+
"}\n\n"+
"ul.suckerfish.vertical li a {\n"+
" padding: 0.5em 1em 0.5em 1em;\n"+
" border-top:1px solid #fff;\n"+
"}\n\n"+
"ul.suckerfish.vertical, ul.suckerfish.vertical ul {\n"+
" line-height:1.4em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { \n"+
" margin: -2.4em 0 0 10.9em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {\n"+
" border: 0px solid #FFF;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{\n"+
" padding-right:1.1em;\n"+
"}\n\n"+
"ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {\n"+
" border-bottom:1px solid #fff;\n"+
"}\n\n"+
"/***** END LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
"/*}}}*/";
store.addNotification("StyleSheetDropDownMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).
Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers.
''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.
''Access and Modify Tiddler Data''
You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields.
These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//
''Data Representation in a Tiddler''
The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]].
//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}
The data section is not displayed when viewing the tiddler (see also "The showData Macro").
Beside the data section a tiddler may have all kind of other content.
Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.
''Saving Changes''
The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.
''Notifications''
No notifications are sent when a tiddler's data value is changed through the "setData" methods.
''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.
''The showData Macro''
By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:
''Syntax:''
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
!Revision history
* v1.0.6 (2006-08-26)
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed:
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features:
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed:
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// DataTiddlerPlugin
//============================================================================
//============================================================================
// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {
version.extensions.DataTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006, 7, 26),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) {
TiddlyWiki.prototype.getTiddler = function(title) {
var t = this.tiddlers[title];
return (t !== undefined && t instanceof Tiddler) ? t : null;
};
}
//============================================================================
// DataTiddler Class
//============================================================================
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
function DataTiddler() {
}
DataTiddler = {
// Function to stringify a JavaScript value, producing the text for the data section content.
// (Must match the implementation of DataTiddler.parse.)
//
stringify : null,
// Function to parse the text for the data section content, producing a JavaScript value.
// (Must match the implementation of DataTiddler.stringify.)
//
parse : null
};
// Ensure access for IE
window.DataTiddler = DataTiddler;
// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------
// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};
// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler+ "("+t+")";
}
DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};
// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...)
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataObject(t);
};
// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.readDataSectionText(t);
};
// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------
// Internal.
//
// The original JSONError is not very user friendly,
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
if (ex.name == 'JSONError') {
ex.toString = function() {
return ex.name + ": "+ex.message+" ("+ex.text+")";
};
}
return ex;
};
// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
if (t.dataObject === undefined) {
var data = DataTiddler.readData(t);
t.dataObject = (data) ? data : {};
}
return t.dataObject;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
return (value === undefined) ? defaultValue : value;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
var oldValue = data[field];
if (value == defaultValue) {
if (oldValue !== undefined) {
delete data[field];
DataTiddler.save(tiddler);
}
return;
}
data[field] = value;
DataTiddler.save(tiddler);
};
// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
if (matches === null || !matches[2]) {
return null;
}
return matches[2];
};
// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
var text = DataTiddler.readDataSectionText(tiddler);
try {
return text ? DataTiddler.parse(text) : null;
} catch(ex) {
throw DataTiddler.extendJSONError(ex);
}
};
// Internal.
//
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
return DataTiddler.stringify(data);
};
// Internal.
//
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
var index = s.indexOf(subString, startIndex);
while ((index > 0) && (s[index-1] == '~')) {
index = s.indexOf(subString, index+1);
}
return index;
};
// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
// Special care must be taken to handle "<data>" and "</data>" texts inside
// a data section.
// Also take care not to use an escaped <data> (i.e. "~<data>") as the start
// of a data section. (Same for </data>)
// NOTE: we are explicitly searching for a data section that contains a JSON
// string, i.e. framed with braces. This way we are little bit more robust in
// case the tiddler contains unescaped texts "<data>" or "</data>". This must
// be changed when using a different stringifier.
var startTagText = "<data>{";
var endTagText = "}</data>";
var startPos = 0;
// Find the first not escaped "<data>".
var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
if (startDataTagIndex < 0) {
return null;
}
// Find the *last* not escaped "</data>".
var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
if (endDataTagIndex < 0) {
return null;
}
var nextEndDataTagIndex;
while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
endDataTagIndex = nextEndDataTagIndex;
}
return {
prefixEnd: startDataTagIndex,
dataStart: startDataTagIndex+(startTagText.length)-1,
dataEnd: endDataTagIndex,
suffixStart: endDataTagIndex+(endTagText.length)
};
};
// Internal.
//
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
var text = tiddler.text;
var info = DataTiddler.getDataSectionInfo(text);
if (!info) {
return null;
}
var prefix = text.substr(0,info.prefixEnd);
var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
var suffix = text.substr(info.suffixStart);
return [text, prefix, data, suffix];
};
// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change).
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected.
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send.
//
// This method should only be called when the data really has changed.
//
// @param tiddler
// the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
var prefix;
var suffix;
if (matches === null) {
prefix = tiddler.text;
suffix = "";
} else {
prefix = matches[1];
suffix = matches[3];
}
var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
var newText =
(dataText !== null)
? prefix + "<data>" + dataText + "</data>" + suffix
: prefix + suffix;
if (newText != tiddler.text) {
// make the change in the tiddlers text
// ... see DataTiddler.MyTiddlerChangedFunction
tiddler.isDataTiddlerChange = true;
// ... do the action change
tiddler.set(
tiddler.title,
newText,
config.options.txtUserName,
config.options.chkForceMinorUpdate? undefined : new Date(),
tiddler.tags);
// ... see DataTiddler.MyTiddlerChangedFunction
delete tiddler.isDataTiddlerChange;
// Mark the store as dirty.
store.dirty = true;
// AutoSave if option is selected
if(config.options.chkAutoSave) {
saveChanges();
}
}
};
// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
// Remove the data object from the tiddler when the tiddler is changed
// by code other than DataTiddler code.
//
// This is necessary since the data object is just a "cached version"
// of the data defined in the data section of the tiddler and the
// "external" change may have changed the content of the data section.
// Thus we are not sure if the data object reflects the data section
// contents.
//
// By deleting the data object we ensure that the data object is
// reconstructed the next time it is needed, with the data defined by
// the data section in the tiddler's text.
// To indicate that a change is a "DataTiddler change" a temporary
// property "isDataTiddlerChange" is added to the tiddler.
if (this.dataObject && !this.isDataTiddlerChange) {
delete this.dataObject;
}
// call the original code.
DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};
//============================================================================
// Formatters
//============================================================================
// This formatter ensures that "~<data>" is rendered as "<data>". This is used to
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
name: "data-escape",
match: "~<\\/?data>",
handler: function(w) {
w.outputText(w.output,w.matchStart + 1,w.nextMatch);
}
} );
// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
name: "data",
match: "<data>",
handler: function(w) {
var info = DataTiddler.getDataSectionInfo(w.source);
if (info && info.prefixEnd == w.matchStart) {
w.nextMatch = info.suffixStart;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
} );
//============================================================================
// Tiddler Class Extension
//============================================================================
// "Hijack" the changed method ---------------------------------------------------
DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;
// Define accessor methods -------------------------------------------------------
// Returns the value of the given data field of the tiddler. When no such field
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
return (field)
? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
: DataTiddler.getTiddlerDataObject(this);
};
// Sets the value of the given data field of the tiddler to the value. When the
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};
//============================================================================
// showData Macro
//============================================================================
config.macros.showData = {
// Standard Properties
label: "showData",
prompt: "Display the values stored in the data section of the tiddler"
};
config.macros.showData.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the optional "JSON"
var showInJSONFormat = false;
if ((i < params.length) && params[i] == "JSON") {
i++;
showInJSONFormat = true;
}
var tiddlerName = story.findContainingTiddler(place).id.substr(7);
if (i < params.length) {
tiddlerName = params[i];
i++;
}
// --- Processing ------------------------------------------
try {
if (showInJSONFormat) {
this.renderDataInJSONFormat(place, tiddlerName);
} else {
this.renderDataAsTable(place, tiddlerName);
}
} catch (e) {
this.createErrorElement(place, e);
}
};
config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
var text = DataTiddler.getDataText(tiddlerName);
if (text) {
createTiddlyElement(place,"pre",null,null,text);
}
};
config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
var text = "|!Name|!Value|\n";
var data = DataTiddler.getDataObject(tiddlerName);
if (data) {
for (var i in data) {
var value = data[i];
text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
}
}
wikify(text, place);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.showData.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".showDataError{color: #ffffff;background-color: #880000;}",
"showData");
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... TiddlyWiki Core
/*global createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global DataTiddler */
// ... JSON
/*global JSON */
/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
throw a 'JSONError' exception if there is an error.
*/
var JSON = {
copyright: '(c)2005 JSON.org',
license: 'http://www.crockford.com/JSON/license.html',
/*
Stringify a JavaScript value, producing a JSON text.
*/
stringify: function (v) {
var a = [];
/*
Emit a string.
*/
function e(s) {
a[a.length] = s;
}
/*
Convert a value.
*/
function g(x) {
var c, i, l, v;
switch (typeof x) {
case 'object':
if (x) {
if (x instanceof Array) {
e('[');
l = a.length;
for (i = 0; i < x.length; i += 1) {
v = x[i];
if (typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(v);
}
}
e(']');
return;
} else if (typeof x.toString != 'undefined') {
e('{');
l = a.length;
for (i in x) {
v = x[i];
if (x.hasOwnProperty(i) &&
typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(i);
e(':');
g(v);
}
}
return e('}');
}
}
e('null');
return;
case 'number':
e(isFinite(x) ? +x : 'null');
return;
case 'string':
l = x.length;
e('"');
for (i = 0; i < l; i += 1) {
c = x.charAt(i);
if (c >= ' ') {
if (c == '\\' || c == '"') {
e('\\');
}
e(c);
} else {
switch (c) {
case '\b':
e('\\b');
break;
case '\f':
e('\\f');
break;
case '\n':
e('\\n');
break;
case '\r':
e('\\r');
break;
case '\t':
e('\\t');
break;
default:
c = c.charCodeAt();
e('\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16));
}
}
}
e('"');
return;
case 'boolean':
e(String(x));
return;
default:
e('null');
return;
}
}
g(v);
return a.join('');
},
/*
Parse a JSON text, producing a JavaScript value.
*/
parse: function (text) {
var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
token,
operator;
function error(m, t) {
throw {
name: 'JSONError',
message: m,
text: t || operator || token
};
}
function next(b) {
if (b && b != operator) {
error("Expected '" + b + "'");
}
if (text) {
var t = p.exec(text);
if (t) {
if (t[2]) {
token = null;
operator = t[2];
} else {
operator = null;
try {
token = eval(t[1]);
} catch (e) {
error("Bad token", t[1]);
}
}
text = text.substring(t[0].length);
} else {
error("Unrecognized token", text);
}
} else {
token = operator = undefined;
}
}
function val() {
var k, o;
switch (operator) {
case '{':
next('{');
o = {};
if (operator != '}') {
for (;;) {
if (operator || typeof token != 'string') {
error("Missing key");
}
k = token;
next();
next(':');
o[k] = val();
if (operator != ',') {
break;
}
next(',');
}
}
next('}');
return o;
case '[':
next('[');
o = [];
if (operator != ']') {
for (;;) {
o.push(val());
if (operator != ',') {
break;
}
next(',');
}
}
next(']');
return o;
default:
if (operator !== null) {
error("Missing value");
}
k = token;
next();
return k;
}
}
next();
return val();
}
};
/***
!Setup the data serialization
***/
DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;
//}}}
*I have to delete MediaWikiAdaptroPlugin ... created MediaWikiAdaptorDud
As I told simon, I copy / pasted / Done but when reloading I get the PluginManager with an error; yet again the script has gotten truncated.
----
!1JULY08:
*--Tried to recreate [[ToDo Tiddler from kronenpj.tiddlyspot|http://kronenpj.tiddlyspot.com/#ToDoSampleEmpty]] ... ToDoPluginDT is well written, calling out requirements as DataTiddlerPlugin and InlineJavascriptPlugin but DataTiddlerPlugin (tooooooo huge!)--
With help from Paul on IRC got it working ... using ''X'' for delete, ^ for up, and v for down.
/***
|Name|CheckboxPlugin|
|Source|http://www.TiddlyTools.com/#CheckboxPlugin|
|Documentation|http://www.TiddlyTools.com/#CheckboxPluginInfo|
|Version|2.4.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Add checkboxes to your tiddler content|
This plugin extends the TiddlyWiki syntax to allow definition of checkboxes that can be embedded directly in tiddler content. Checkbox states are preserved by:
* by setting/removing tags on specified tiddlers,
* or, by setting custom field values on specified tiddlers,
* or, by saving to a locally-stored cookie ID,
* or, automatically modifying the tiddler content (deprecated)
When an ID is assigned to the checkbox, it enables direct programmatic access to the checkbox DOM element, as well as creating an entry in TiddlyWiki's config.options[ID] internal data. In addition to tracking the checkbox state, you can also specify custom javascript for programmatic initialization and onClick event handling for any checkbox, so you can provide specialized side-effects in response to state changes.
!!!!!Documentation
>see [[CheckboxPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to [[CheckboxPluginInfo]]
2008.01.05 [2.4.0] set global "window.place" to current checkbox element when processing checkbox clicks. This allows init/beforeClick/afterClick handlers to reference RELATIVE elements, including using "story.findContainingTiddler(place)". Also, wrap handlers in "function()" so "return" can be used within handler code.
|please see [[CheckboxPluginInfo]] for additional revision details|
2005.12.07 [0.9.0] initial BETA release
<<<
!!!!!Code
***/
//{{{
version.extensions.CheckboxPlugin = {major: 2, minor: 4, revision:0 , date: new Date(2008,1,5)};
//}}}
//{{{
config.checkbox = { refresh: { tagged:true, tagging:true, container:true } };
config.formatters.push( {
name: "checkbox",
match: "\\[[xX_ ][\\]\\=\\(\\{]",
lookahead: "\\[([xX_ ])(=[^\\s\\(\\]{]+)?(\\([^\\)]*\\))?({[^}]*})?({[^}]*})?({[^}]*})?\\]",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
// get params
var checked=(lookaheadMatch[1].toUpperCase()=="X");
var id=lookaheadMatch[2];
var target=lookaheadMatch[3];
if (target) target=target.substr(1,target.length-2).trim(); // trim off parentheses
var fn_init=lookaheadMatch[4];
var fn_clickBefore=lookaheadMatch[5];
var fn_clickAfter=lookaheadMatch[6];
var tid=story.findContainingTiddler(w.output); if (tid) tid=tid.getAttribute("tiddler");
var srctid=w.tiddler?w.tiddler.title:null;
config.macros.checkbox.create(w.output,tid,srctid,w.matchStart+1,checked,id,target,config.checkbox.refresh,fn_init,fn_clickBefore,fn_clickAfter);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} );
config.macros.checkbox = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
if(!(tiddler instanceof Tiddler)) { // if no tiddler passed in try to find one
var here=story.findContainingTiddler(place);
if (here) tiddler=store.getTiddler(here.getAttribute("tiddler"))
}
var srcpos=0; // "inline X" not applicable to macro syntax
var target=params.shift(); if (!target) target="";
var defaultState=params[0]=="checked"; if (defaultState) params.shift();
var id=params.shift(); if (id && !id.length) id=null;
var fn_init=params.shift(); if (fn_init && !fn_init.length) fn_init=null;
var fn_clickBefore=params.shift();
if (fn_clickBefore && !fn_clickBefore.length) fn_clickBefore=null;
var fn_clickAfter=params.shift();
if (fn_clickAfter && !fn_clickAfter.length) fn_clickAfter=null;
var refresh={ tagged:true, tagging:true, container:false };
this.create(place,tiddler.title,tiddler.title,0,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter);
},
create: function(place,tid,srctid,srcpos,defaultState,id,target,refresh,fn_init,fn_clickBefore,fn_clickAfter) {
// create checkbox element
var c = document.createElement("input");
c.setAttribute("type","checkbox");
c.onclick=this.onClickCheckbox;
c.srctid=srctid; // remember source tiddler
c.srcpos=srcpos; // remember location of "X"
c.container=tid; // containing tiddler (may be null if not in a tiddler)
c.tiddler=tid; // default target tiddler
c.refresh = {};
c.refresh.container = refresh.container;
c.refresh.tagged = refresh.tagged;
c.refresh.tagging = refresh.tagging;
place.appendChild(c);
// set default state
c.checked=defaultState;
// track state in config.options.ID
if (id) {
c.id=id.substr(1); // trim off leading "="
if (config.options[c.id]!=undefined)
c.checked=config.options[c.id];
else
config.options[c.id]=c.checked;
}
// track state in (tiddlername|tagname) or (fieldname@tiddlername)
if (target) {
var pos=target.indexOf("@");
if (pos!=-1) {
c.field=pos?target.substr(0,pos):"checked"; // get fieldname (or use default "checked")
c.tiddler=target.substr(pos+1); // get specified tiddler name (if any)
if (!c.tiddler || !c.tiddler.length) c.tiddler=tid; // if tiddler not specified, default == container
if (store.getValue(c.tiddler,c.field)!=undefined)
c.checked=(store.getValue(c.tiddler,c.field)=="true"); // set checkbox from saved state
} else {
var pos=target.indexOf("|"); if (pos==-1) var pos=target.indexOf(":");
c.tag=target;
if (pos==0) c.tag=target.substr(1); // trim leading "|" or ":"
if (pos>0) { c.tiddler=target.substr(0,pos); c.tag=target.substr(pos+1); }
if (!c.tag.length) c.tag="checked";
var t=store.getTiddler(c.tiddler);
if (t && t.tags)
c.checked=t.isTagged(c.tag); // set checkbox from saved state
}
}
// trim off surrounding { and } delimiters from init/click handlers
if (fn_init) c.fn_init="(function(){"+fn_init.trim().substr(1,fn_init.length-2)+"})()";
if (fn_clickBefore) c.fn_clickBefore="(function(){"+fn_clickBefore.trim().substr(1,fn_clickBefore.length-2)+"})()";
if (fn_clickAfter) c.fn_clickAfter="(function(){"+fn_clickAfter.trim().substr(1,fn_clickAfter.length-2)+"})()";
c.init=true; c.onclick(); c.init=false; // compute initial state and save in tiddler/config/cookie
},
onClickCheckbox: function(event) {
window.place=this;
if (this.init && this.fn_init) // custom function hook to set initial state (run only once)
{ try { eval(this.fn_init); } catch(e) { displayMessage("Checkbox init error: "+e.toString()); } }
if (!this.init && this.fn_clickBefore) // custom function hook to override changes in checkbox state
{ try { eval(this.fn_clickBefore) } catch(e) { displayMessage("Checkbox onClickBefore error: "+e.toString()); } }
if (this.id)
// save state in config AND cookie (only when ID starts with 'chk')
{ config.options[this.id]=this.checked; if (this.id.substr(0,3)=="chk") saveOptionCookie(this.id); }
if (this.srctid && this.srcpos>0 && (!this.id || this.id.substr(0,3)!="chk") && !this.tag && !this.field) {
// save state in tiddler content only if not using cookie, tag or field tracking
var t=store.getTiddler(this.srctid); // put X in original source tiddler (if any)
if (t && this.checked!=(t.text.substr(this.srcpos,1).toUpperCase()=="X")) { // if changed
t.set(null,t.text.substr(0,this.srcpos)+(this.checked?"X":"_")+t.text.substr(this.srcpos+1),null,null,t.tags);
if (!story.isDirty(t.title)) story.refreshTiddler(t.title,null,true);
store.setDirty(true);
}
}
if (this.field) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
// set the field value in the target tiddler
store.setValue(this.tiddler,this.field,this.checked?"true":"false");
// DEBUG: displayMessage(this.field+"@"+this.tiddler+" is "+this.checked);
}
if (this.tag) {
if (this.checked && !store.tiddlerExists(this.tiddler))
store.saveTiddler(this.tiddler,this.tiddler,"",config.options.txtUserName,new Date());
var t=store.getTiddler(this.tiddler);
if (t) {
var tagged=(t.tags && t.tags.indexOf(this.tag)!=-1);
if (this.checked && !tagged) { t.tags.push(this.tag); store.setDirty(true); }
if (!this.checked && tagged) { t.tags.splice(t.tags.indexOf(this.tag),1); store.setDirty(true); }
}
// if tag state has been changed, update display of corresponding tiddlers (unless they are in edit mode...)
if (this.checked!=tagged) {
if (this.refresh.tagged) {
if (!story.isDirty(this.tiddler)) // the TAGGED tiddler in view mode
story.refreshTiddler(this.tiddler,null,true);
else // the TAGGED tiddler in edit mode (with tags field)
config.macros.checkbox.refreshEditorTagField(this.tiddler,this.tag,this.checked);
}
if (this.refresh.tagging)
if (!story.isDirty(this.tag)) story.refreshTiddler(this.tag,null,true); // the TAGGING tiddler
}
}
if (!this.init && this.fn_clickAfter) // custom function hook to react to changes in checkbox state
{ try { eval(this.fn_clickAfter) } catch(e) { displayMessage("Checkbox onClickAfter error: "+e.toString()); } }
// refresh containing tiddler (but not during initial rendering, or we get an infinite loop!) (and not when editing container)
if (!this.init && this.refresh.container && this.container!=this.tiddler)
if (!story.isDirty(this.container)) story.refreshTiddler(this.container,null,true); // the tiddler CONTAINING the checkbox
return true;
},
refreshEditorTagField: function(title,tag,set) {
var tagfield=story.getTiddlerField(title,"tags");
if (!tagfield||tagfield.getAttribute("edit")!="tags") return; // if no tags field in editor (i.e., custom template)
var tags=tagfield.value.readBracketedList();
if (tags.contains(tag)==set) return; // if no change needed
if (set) tags.push(tag); // add tag
else tags.splice(tags.indexOf(tag),1); // remove tag
for (var t=0;t<tags.length;t++) tags[t]=String.encodeTiddlyLink(tags[t]);
tagfield.value=tags.join(" "); // reassemble tag string (with brackets as needed)
return;
}
}
//}}}
cdent@peermore.com
Date: Thu, 5 Jun 2008 17:21:34 -0700 (PDT)
Subject: [[TiddlyWeb and verticals|http://groups.google.com/group/TiddlyWikiDev/browse_thread/thread/f2a91f53bed8aee8/7bf99dd4253547a7?hl=en]]
I did some experimenting tonight with TiddlyWeb and TeamTasks (a TiddlyWiki vertical for managing tasks across group) to see where some of the holes are in TiddlyWeb. I figured I'd report here to get some feedback from folk.
My goal: To produce a working instance of TeamTasks produced from a recipe and tiddlers in Tiddlyweb.
Summary: Almost but not quite. The barriers are low.
First I started up a TiddlyWeb instance in my current checkout, running on localhost:
python server.py 0.0.0.0 8080
Then I located a TeamTasks generated TiddlyWiki HTML file. I found that here:
http://svn.tiddlywiki.org/Trunk/contributors/PhilHawksworth/verticals...
I copied that file into my local directory to the name 'wiki'. With the TiddlyWeb server running, I ran python test/importer.py. This script reads in a TiddlyWiki file slicing and dicing it in to individual tiddlers. It then makes HTTP requests to the server to create a bag named 'wiki', a recipe named 'wiki' listing the new bag and to PUT each of the tiddlers found in the tiddlywiki.
I did some file copying to get TiddlyWebAdaptorPlugin and TiddlyWebAutoSavePlugin into the 'wiki' bag.
I loaded the TiddlyWiki generated by /recipes/wiki/tiddlers.wiki into my browser. There were no errors and things looked lovely.
The new user wizard did not display as expected. Didn't figure out what was up here.
Each time I edited a tiddler I got an alert saying that the page needed to be saved before I could edit. My changes were sent to the sever anyway. Turning off AutoSave in the options removed the alert.
Creating a new tasks created a new tiddler, but it was not saved to the server. This is because the newly generated did not have the various server.* fields set. Without those fields the TiddlyWebAdaptorPlugin does not pay attention to the tiddler.
Presumably we can set the defaults for those things.
That's about as far as I got before I decided to write this message. I did not get into creating task views. Here's some comments on what I learned:
* The test/importer.py script needs to take some arguments about the names of the bag and recipe it creates. It would be good for it to provide some feedback.
* test/importer needs to take input on stdin instead of from a statically named file.
* TiddlyWeb should come preloaded with the TiddlyWebAdaptorPlugin and TiddlyWebAutoSavePlugin in two bags users can choose to include in their recipes.
* AutoSave and TiddlyWebAutoSavePlugin do not play well together so the latter should probably disable that option, as we do not want to save the whole TiddlyWiki, just individual tiddlers.
* There needs to be an easy way (or exposure of the easy way) to set server.host, server.type, and server.workspace and/or server.bag so that new tiddlers get saved to the server.
* A proper multi-user use of this sort of thing would require users and authentication. That's coming soon to a TiddlyWeb near you.
* TiddlyWeb does some fairly advanced things to avoid edit contention. It announces them with HTTP 412 respones. The adaptor and auto save plugins don't pay much attention to that stuff. It should.
* If two or more people are working on the same set of tasks but in their own browsers their respective TiddlyWikis need some way of being updated when the state of those tasks changes. Consider, for example, a tiddler that is doing live display of task statuses. In the current situation it can only display what it knows about the tiddlers contained within itself. Ideally it will be updated when a task changes on the server. There are a few options for this: each tiddler could poll the server to know if it has changed (polling not such a good idea), a plugin could keep a Comet[1]-like connection open to the server and receive notifications of changes, other requests to the server (when tiddlers are saved) could include out of band updates in the headers.
The gist here is that verticals can work fine if two things are worked out:
* New tiddlers are generated with awareness of where they need to go to be saved (the server.* fields are set).
* The vertical is resilient in the face of what we might call tiddler latency: the tiddler in the current tiddlywiki may not be the most up to date revision of that tiddler.
[1] http://simonwillison.net/2007/Dec/5/comet/
/***
|''Name:''|MediaWikiAdaptorPlugin|
|''Description:''|Adaptor for moving and converting data from MediaWikis|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Source:''|http://www.martinswiki.com/#MediaWikiAdaptorPlugin |
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/adaptors/MediaWikiAdaptorPlugin.js |
|''Version:''|0.5.8|
|''Date:''|Jul 27, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]] |
|''~CoreVersion:''|2.2.0|
|''Max number of tiddlers to download''|<<option txtMediaAdaptorLimit>>|
MediaWiki REST documentation is at:
http://meta.wikimedia.org/w/api.php
http://meta.wikimedia.org/w/query.php
***/
//''NFG''// ... gets kinda tedious, this does.
<script>
var idcomments_acct = 'f9ba6dac8475191095289bf2e1bb6b80';
var idcomments_post_id;
var idcomments_post_url;
</script>
<span id="IDCommentsPostTitle" style="display:none"></span>
<script type='text/javascript' src='http://www.intensedebate.com/js/genericCommentWrapperV2.js'></script>
*I'm having success with ~IFrame, but not with Javascript ... see [[IFrame2]] ... that's a fine little widget. A cheap/sleazy workaround is to create a document with just the script in it, then load that into ~IFrame ... see AjaxianIFrame2
* Tried using ccUpload ... no joy. see UploadContents.
* Created ViewTemplate and StyledTable
<<ToC>>
!Ick ... --something about using ! to create a header goes insane.--
And now this is perfectly fine. And, as can be seen at the top of this Tiddler, the ~ToC plugin is working fine.
{{{*blink*}}}
![[TiddlySnip|http://tiddlysnip.com/]] ... //''gotta luv it''!//
Selected a block of text and saved it as a Tiddler on my local file. Then did the same using upload to my hosted version. Then edited the local TW and uploaded that. A lovely functionality!
----
!Ripped [[RippleRap RoadMap]] from [[that workspace|http://wiki.osmosoft.com/alpha/cctiddly#Roadmap]] !
----
![[Active workspaces in /alpha/|WorkSpaces]];
[[the comprehensive list|http://wiki.osmosoft.com/alpha/handle/listWorkspaces.php]]
----
!''RFE'':
functional equivalent of --"what links here"-- (some plugin adds "References" to the edit toolbar) and "orphan pages" in MediaWiki
!''//~ToDo//'':
* [[MoveablePanelPlugin|http://www.tiddlytools.com/#MoveablePanelPluginInfo]], found in [[comments workspace|http://wiki.osmosoft.com/alpha/comments]]
* ''NB'': --the [[RippleRap workspace|http://wiki.osmosoft.com/alpha/cctiddly]] has some sort of comment function running.-- Got it ... SimpleCommentsPlugin
* Implement [[pipePluginDemo]]
* Checkout [[TableSortingPlugin|http://wiki.osmosoft.com/alpha/smm#TableSortingPlugin]]
* Fix DcTableOfContentsPlugin ... awesome weird display ... [[the original|http://www.zagware.com/tw/plugins.html#DcTableOfContentsPlugin]] shows no such madness. I just tried using it and it incremented font size after each and every header. And just now I imported TiddlerToCPlugin from [[FND's site|http://devpad.tiddlyspot.com/#TiddlerToCPlugin]] and it does precisely the same thing.
* Explore [[ForEachTiddler|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin]] and also [[RippleRap ToDo|http://wiki.osmosoft.com/alpha/rippleraptodolist]] and also [[GoToPlugin|http://www.tiddlytools.com/#GotoPlugin]]
----
!9 July 2008
Not much to write.
* righthand sidebar LoginStatus ... it really could carry a login form (2 rows + a button)
//from ''[[RippleRap's /alpha/ workspace|http://wiki.osmosoft.com/alpha/cctiddly#Roadmap]]''//
Whats going on with ccTiddly? We’ve now got a couple of user groups within BT using ccTiddly. Their feedback is driving a wave of improvements that I’m working on with CoolCold, the man who originally created ccTiddly. The areas we’ve been looking at are:
Self-service Workspace CreationThe new version of ccTiddly will allows users to create their own ccTiddly workspaces, which is a (more or less) a complete independent wiki with it’s own security permissions.
Reusable Master WorkspacesccTiddly 2.x introduces the concept of master workspaces. A “master workspace†allows a set of tiddlers to be packaged up and included in several different workspaces. This allows common content such as themes to be shared between workspaces. Because the links are dynamic, it is also possible to change a tiddler from a master workspace and have the change automatically appear in workspaces that use that master.
User ManagementThe new version of ccTiddly will have new user management and security that allows permissions to be set on a per-workspace basis for individual users and groups. Although we’re currently working with a custom user database, I’ve got experimental support for both LDAP and OpenID.
Image and Attachment Support Users will be able to upload images and other attachments to a workspace .
Import Support Users will also be able to upload a standalone TiddlyWiki file so that it can be imported into a ccTiddly workspace.
Personal TiddlersUsers will be able to create custom personal tiddlers which will persist across all workspaces they access on a server, allowing advanced users to be able to have settings applied consistently across all their workspaces
Active workspaces in /alpha/ ([[the comprehensive list|http://wiki.osmosoft.com/alpha/handle/listWorkspaces.php]]):
----
[[SMM|http://wiki.osmosoft.com/alpha/smm]]; [[comments|http://wiki.osmosoft.com/alpha/comments]]; [[RippleRap|http://wiki.osmosoft.com/alpha/cctiddly]]; [[OsmoSoft's est|http://wiki.osmosoft.com/alpha/est]]; [[ActivityDiagram|http://wiki.osmosoft.com/alpha/ActivityDiagram]]; [[OsmoImport *blink*|http://wiki.osmosoft.com/alpha/osmoimport]]; [[Martin's Kubrick|http://wiki.osmosoft.com/alpha/martin]]; [[RippleRap ToDo|http://wiki.osmosoft.com/alpha/rippleraptodolist]]; [[JP Rangaswami's TiddlyCalcutta|http://wiki.osmosoft.com/alpha/TiddlyCalcutta]]; [[FND's Full Reference|http://wiki.osmosoft.com/alpha/ReferenceManual#[[Full Reference]]; [[Agile Cookbook|http://wiki.osmosoft.com/alpha/agilecookbook]]; [[3CRUD|http://wiki.osmosoft.com/alpha/workspace3CRUD]]; [[assorted goodness|http://wiki.osmosoft.com/alpha/1]]; [[PaliEnglish (lots of plugins)|http://wiki.osmosoft.com/alpha/998]]
----
//ripped from [[OsmoSoft's /alpha/ workspace|http://wiki.osmosoft.com/alpha/est]]
<<pipePlugin http://pipes.yahoo.com/pipes/pipe.run?_id=NDqmn7Fm3BG4hHj0iHrL0A&_render=json&_callback=config.macros.pipePlugin.JSONparse 10 250>>
//{{{
config.macros.pipePlugin = {};
config.macros.pipePlugin.context = {};
config.macros.pipePlugin.handler = function(place, name, params)
{
this.context.place = place;
this.context.name = name;
this.context.params = params;
var newScript = document.createElement('script');
newScript.id = 'temp_script';
newScript.type = 'text/javascript';
newScript.onload = config.macros.pipePlugin.removeScript;
newScript.src = params[0];
place.appendChild(newScript);
};
config.macros.pipePlugin.removeScript = function() {
var k = document.getElementById("temp_script");
removeNode(k);
};
config.macros.pipePlugin.JSONparse = function(response) {
JSON = {};
JSON.response = eval(response);
JSON.blogtitle = JSON.response.value.title;
JSON.blogitems = JSON.response.value.items;
// Iterate through the blog items
var limit = this.context.params[1];
limit = ((limit && limit > JSON.blogitems.length) ? JSON.blogitems.length : limit);
for (var i=0; i<limit; i++) {
var item = JSON.blogitems[i];
var item_title = item.title;
var item_link = item.link;
// pick the right author node
var item_author = (function() {
return (item["dc:creator"] || (item.author && item.author.name));
})();
var heading = item_title;
headingelement = document.createElement("h3");
headingelement_link = document.createElement("a");
headingelement_link.setAttribute("href",item_link);
headingelement_link.setAttribute("target","_blank");
headingelement.appendChild(headingelement_link).appendChild(document.createTextNode(heading));
this.context.place.appendChild(headingelement);
// var pubDate = new Date(item.pubDate);
var date_regex = /(.)*?200(7|8|9)/mg;
var pubDate = item.pubDate.match(date_regex)[0];
var author_line = "posted by " + item_author + " on " + pubDate;
createTiddlyElement(this.context.place,"h4",null,null,author_line);
// pick the right content node
var raw_content = new String();
raw_content = (function() {
return (item["content:encoded"] || (item.content && item.content.content) || item["description"]);
})();
var content = raw_content.renderHtmlText();
content = content.renderHtmlEscapedEntities();
var para = document.createElement("p");
var summary_limit = this.context.params[2];
if (summary_limit) { writeCodeSummary(summary_limit,content,para); }
else writeCode(content,para);
this.context.place.appendChild(para);
}
};
// renderHtmlText puts a string through the browser render process and then extracts the text
// useful to turn HTML entities into literals such as ' to '
// this, annoyingly, doesn't cope with entities such as ’ - see renderHtmlEscapedEntities
// below for that
// NB: At some point, someone should create a utility function that just creates a text version
// of any HTML string, coping with any character encodings - as if it had been rendered in the
// browser and then copied out. This would combine renderHtmlText, renderHtmlEscapedEntities
// and writeCode or writeCodeSummary
String.prototype.renderHtmlText = function() {
var e = createTiddlyElement(document.body,"div");
e.innerHTML = this;
var text = getPlainText(e);
removeNode(e);
return text;
};
// renderHtmlEscapedEntities takes a HTML string which has already been run through
// renderHtmlText to deal with converting entities such as ' to '
// It then converts remaining entities such as ’ to '
String.prototype.renderHtmlEscapedEntities = function() {
var entity_match = /&#(.*?);/mg;
entities = this.replace(entity_match,function(string_match,matches) {
var word = string_match.substring(2,string_match.length-1);
var new_word = String.fromCharCode(word);
return new_word;
});
return entities;
};
// Creates a sub-tree under a given element
// copied from O'Reilly Javascript Library
function writeCode(s, pointer) {
var parent, tag, j;
for ( var i = 0; i < s.length; i++) {
var c = s.charAt(i);
if (c == "<") {
var j = s.indexOf(">", i + 1);
tag = s.substring(i, j + 1);
if (tag.charAt(tag.length - 2) == "/") {
if (pointer != null && pointer.nodeType == 3) {
pointer = pointer.parentNode;
}
pointer.appendChild(createElementFromString(tag));
} else if (tag.charAt(1) != "/") {
if (pointer != null && pointer.nodeType == 3) {
pointer = pointer.parentNode;
}
pointer = pointer.appendChild(createElementFromString(tag));
} else {
if (pointer.parentNode != null &&
pointer.parentNode.parentNode != null) {
pointer = pointer.parentNode.parentNode;
}
}
i = j;
} else {
if (pointer.nodeType == 3) {
n = s.indexOf("<", i + 1);
if (n == -1) {
pointer.nodeValue += s.substr(i);
i = s.length;
} else {
pointer.nodeValue += s.substring(i, n);
i = n - 1;
}
} else {
pointer = pointer.appendChild(document.createTextNode(c));
}
}
}
}
// Creates a plaintext summary of a given HTML string
// based on writeCode() from O'Reilly Javascript Library
function writeCodeSummary(limit, s, pointer) {
var parent, tag, j;
limit = (limit < s.length ? limit : s.length);
// count keeps track of the number of text characters added
var count = 0;
for ( var i = 0; count < limit; i++) {
var c = s.charAt(i);
// Ignore tags
if (c == "<") {
var j = s.indexOf(">", i + 1);
i = j;
} else {
if (pointer.nodeType == 3) {
n = s.indexOf("<", i + 1);
if (n == -1) {
pointer.nodeValue += s.substr(i);
i = s.length;
count += s.length;
} else {
// check we're not adding too many characters
// n - i is the length of the string we are adding
// limit - count is the number we have left to play with
var extratext;
if (n - i > limit - count) {
extratext = s.substring(i, i + (limit - count));
} else extratext = s.substring(i, n);
pointer.nodeValue += extratext;
count += extratext.length;
i = n - 1;
}
} else {
pointer = pointer.appendChild(document.createTextNode(c));
count++;
}
}
}
}
// parse a string and create an element from it
// based on O'Reilly Javascript Library code
function createElementFromString(str) {
var node, a = str.match(/<(\w+)(\s+)?([^>]+)?>/);
if (a != null) {
node = document.createElement(a[1]);
if (a[3] != null) {
var attrs = a[3].split(" ");
if (attrs.length > 0) {
for ( var i = 0; i < attrs.length; i++) {
var att = attrs[i].split("=");
if (att[0].length > 0 &&
att[0] != "/" && att[1] && att[1].length != 2) {
var a_n = document.createAttribute(att[0]);
a_n.value = att[1].replace(/^['"](.+)['"]$/, "$1");
node.setAttributeNode(a_n);
}
}
}
}
}
return node;
}
//}}}
/***
|Name|SimpleCommentsPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#SimpleCommentsPlugin]]|
|Version|0.7|
|Author|FND|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|add comments to a tiddler|
!Usage
Add {{{<<addComment>>}}} to the desired tiddler(s).
Alternatively, add the following to the tiddler toolbar (usually in ViewTemplate, {{{<div class='toolbar' macro='...'>}}}): {{{addComment}}} (currently untested)
''N.B.:'' For now, TiddlyWiki needs to be saved manually after adding a comment, thus making this plugin rather unsuitable for read-only TiddlyWikis.
!Changelog
!!v0.5 (2007-05-08)
* initial release
!!v0.6 (2007-05-10)
* moved required styles into a shadow tiddler
!!v0.7 (2007-05-14)
* complete rewrite from DOM-based to string-based processing
!Issues / To Do
* proper creation of command buttons
* global option and/or macro parameter for reverseOrder
* revise CSS properties
* review code (esp. section marked with DEBUG)
* some functions/routines might be redundant (i.e. already present in the TiddlyWiki core, e.g. {{{trim()}}}, {{{IsoTimestamp()}}} & {{{zeroPad()}}}?)
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetSimpleComments shadow tiddler)
*/
config.shadowTiddlers.StyleSheetSimpleComments = "/*{{{*/\n"
+ ".comments {\n\tmargin-top: 2em;\n\tpadding: 1em 4px 4px;\n\tborder-top: 2px ridge #AAA;\n\tbackground-color: #F8F8F8;\n}\n\n"
+ ".comments .comment {\n\tmargin: 0.5em 1em;\n\tpadding: 4px;\n\tborder: 1px solid #AAA;\n\tbackground-color: #FFF;\n}\n\n"
+ ".comments .comment h1,\n.comments .comment h2 {\n\tmargin: 0 0 0.2em;\n\tpadding: 0;\n\tborder-bottom: 1px solid #AAA;\n\tbackground-color: transparent;\n}\n\n"
+ ".comments .comment h1 {\n\tfloat: right;\n}\n\n"
+ ".comments .comment p {\n\tmargin: 0 0 0.2em;\n}\n"
+ "/*}}}*/";
store.addNotification("StyleSheetSimpleComments", refreshStyles);
/*
** Command Buttons
*/
/* Macro Button */
// adapted from Jack's DoBackupMacro (http://groups.google.com/group/TiddlyWiki/browse_thread/thread/5f1123d08bdadeac/86245d5e4bbe846c)
config.macros.addComment = { label: "Add comment", prompt: "Add a new comment" }; // DEBUG: prompt not needed!?
config.macros.addComment.handler = function(place) {
if(!readOnly) {
createTiddlyButton(place, this.label, this.prompt, function() {
addTiddlerComment(this);
return false; // DEBUG: ?
}, null, null, this.accessKey
); // DEBUG - to do: look up createTiddlyButton()'s parameters
}
}
/* Toolbar Button */
config.commands.addComment = { text: "Add comment", tooltip: "Add a comment" }
config.commands.addComment.handler = function() {
addTiddlerComment(this); // DEBUG: does that work?
}
/*
** Script
*/
// adapted from Eric Shulman's CommentScript (http://www.tiddlytools.com/#CommentScript)
addTiddlerComment = function(place) {
// select current tiddler
var here = story.findContainingTiddler(place);
if (!here) {
alert("error: no tiddler specified");
return;
}
var title = here.getAttribute("tiddler");
var tiddler = store.getTiddler(title);
// retrieve tiddler sections
var tiddlerContentsPre = tiddler.text + "\n";
var tiddlerComments = "";
var tiddlerContentsPost = "";
var RegEx = /^([\S\s]*)\{\{comments\{((?:\{\{comment\{[^}]*\}\}\}|\s+)*)\}\}\}([\S\s]*)$/i; // RegEx provided by Andreas "Qtax" Zetterlund (www.qtax.se)
var tiddlerContents = RegEx.exec(tiddler.text);
if (tiddlerContents != null) {
tiddlerContentsPre = tiddlerContents[1];
tiddlerComments += lTrim(tiddlerContents[2]); // assuming there is only a single comments section per tiddler
tiddlerContentsPost = tiddlerContents[3];
}
// append comment
var reverseOrder = false; // DEBUG: global option!?
if (reverseOrder) {
tiddlerComments = newComment() + "\n" + tiddlerComments;
} else {
tiddlerComments += newComment() + "\n";
}
tiddlerComments = "{{comments{\n" + tiddlerComments + "}}}";
// re-create tiddler contents
tiddlerContents = tiddlerContentsPre + tiddlerComments + tiddlerContentsPost;
// store new tiddler contents
store.saveTiddler(tiddler.title, tiddler.title, tiddlerContents, tiddler.modifier, tiddler.modified, tiddler.tags); // DEBUG: look up saveTiddler()'s parameters
story.refreshTiddler(title, 1, true); // DEBUG: look up refreshTiddler()'s parameters
// DEBUG: save file automatically? (could also be uploaded if the respective plugin is installed)
}
function newComment() {
// get comment
var comment = getComment();
// create comment
if (comment != null) {
// get username
getUserName();
// get timestamp
var now = new Date();
var timestamp = IsoTimestamp(now, true); // use UTC -- DEBUG: use toLocaleString()?; make UTC a macro parameter
// add timestamp and username
comment = "{{comment{\n"
+ "!" + timestamp + "\n"
+ "!!" + config.options.txtUserName + "\n"
+ comment + "\n"
+ "}}}";
}
return comment;
}
function getComment() { // DEBUG: use temporary textarea instead of dialog box?
var comment = prompt("Please enter your comment (wiki markup is allowed).", "");
comment = trim(comment);
if (comment == "") { // disallow empty comments
getComment();
}
return comment;
}
function getUserName() {
if (config.options.txtUserName == "" || config.options.txtUserName == null) { // does not accept "Cancel"!
config.options.txtUserName = prompt("Please enter your username.", config.options.txtUserName);
config.options.txtUserName = trim(config.options.txtUserName);
getUserName(); // check for empty username
}
}
function IsoTimestamp(date, UTC) {
var date = new Date(date)
if (UTC == true) {
date = date.getUTCFullYear() + "-"
+ zeroPad(date.getUTCMonth() + 1, 2) + "-"
+ zeroPad(date.getUTCDate(), 2) + " "
+ zeroPad(date.getUTCHours(), 2) + ":"
+ zeroPad(date.getUTCMinutes(), 2)
+ " UTC";
} else {
date = date.getFullYear() + "-"
+ zeroPad(date.getMonth() + 1, 2) + "-"
+ zeroPad(date.getDate(), 2) + " "
+ zeroPad(date.getHours(), 2) + ":"
+ zeroPad(date.getMinutes(), 2);
}
return date;
}
function zeroPad(number, digits) {
var s = String(number);
while (s.length < digits)
s = '0' + s;
return s;
}
// remove leading whitespaces
function lTrim(str) {
var RE = /^\s*((\S+\s*)*)$/;
return str.replace(RE, "$1");
}
// remove trailing whitespaces
function rTrim(str) {
var RE = /^((\s*\S+)*)\s*$/;
return str.replace(RE, "$1");
}
// remove leading and trailing whitespaces
function trim(str) {
return lTrim(rTrim(str));
}
//}}}
/***
|Name|DcTableOfContentsPlugin|
|Created by|Doug Compton|
|Source|http://www.zagware.com/tw/plugins.html#DcTableOfContentsPlugin|
|Version|0.3.0 - 4/12/2006|
<<showtoc>>
!Description
This macro will insert a table of contents reflecting the headings that are used in a tiddler and will be automatically updated when you make changes. Each item in the table of contents can be clicked on to jump to that heading. It can be used either inside of select tiddlers or inside a system wide template.
A parameter can be used to show the table of contents of a seperate tiddler, <<showtoc tiddlerTitle>>
It will also place a link beside each header which will jump the screen to the top of the current tiddler. This will only be displayed if the current tiddler is using the <<showtoc>> macro.
The appearance of the table of contents and the link to jump to the top can be modified using CSS. An example of this is given below.
!Examples
If you had a tiddler with the following headings
! Heading1
!! Heading2
!! Heading3
!!! Heading4
! Heading5
this table of contents would be automatically generated
*Heading1
**Heading2
**Heading3
***Heading4
*Heading5
!Changing how it looks
To modify the appearance, you can use CSS similiar to the below.
//{{{
.dcTOC ul {
color: red;
list-style-type: lower-roman;
}
.dcTOC a {
color: green;
border: none;
}
.dcTOC a:hover {
background: white;
border: solid 1px;
}
.dcTOCTop {
font-size: 2em;
color: green;
}
//}}}
!Usage
!!Only in select tiddlers
The table of contents above is an example of how to use this macro in a tiddler. Just insert <<showtoc>> in a tiddler on a line by itself.
It can also display the table of contents of another tiddler by using the macro with a parameter, <<showtoc tiddlerTitle>>
!!On every tiddler
It can also be used in a template to have it show on every tiddler. An example ViewTemplate is shown below.
//{{{
<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'>Created <span macro='view created date DD-MM-YY'></span>, updated <span macro='view modified date DD-MM-YY'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class="toc" macro='showtoc'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
//}}}
!History
!!0.3.0 - 04/12/2006
*Added the ability to show the table of contents of a seperate tiddler.
*Fixed an error when a heading had a ~WikiLink in it.
!!0.2.0 - 04/10/2006
*Added the [top] link on headings to jump to the top of the current tiddler.
*The appearance can now be customized using CSS.
*All event handlers now return false.
!!0.1.0 - 04/07/2006
*Initial version
!Code
***/
//{{{
version.extensions.DcTableOfContentsPlugin= {
major: 0, minor: 3, revision: 0,
date: new Date(2006, 4, 12),
type: 'macro',
source: "http://www.zagware.com/tw/plugins.html#DcTableOfContentsPlugin"
};
// Replace heading formatter with our own
for (var n=0; n<config.formatters.length; n++) {
var format = config.formatters[n];
if (format.name == 'heading') {
format.handler = function(w) {
// following two lines is the default handler
var e = createTiddlyElement(w.output, "h" + w.matchLength);
w.subWikify(e, this.terminator);
// Only show [top] if current tiddler is using showtoc
if (w.tiddler.isTOCInTiddler == 1) {
// Create to outter SPAN containing the default CSS values
var span = createTiddlyElement(e, "span");
span.setAttribute("style", "font-size: .5em; color: blue;");
// Create the link to jump to the top
createTiddlyButton(span, " [top]", "Go to top of tiddler", window.scrollToTop, "dcTOCTop", null, null);
}
}
break;
}
}
config.macros.showtoc = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var text = "";
var title = "";
var myTiddler = null;
// Did they pass in a tiddler?
if (params.length) {
title = params[0];
myTiddler = store.getTiddler(title);
} else {
myTiddler = tiddler;
}
if (myTiddler == null) {
wikify("ERROR: Could not find " + title, place);
return;
}
var lines = myTiddler .text.split("\n");
myTiddler.isTOCInTiddler = 1;
// Create to SPAN so the TOC can be customized using CSS
var span = createTiddlyElement(place, "span", null, "dcTOC");
if (lines != null) {
for (var x=0; x<lines.length; x++) {
var line = lines[x];
if (line.substr(0,1) == "!") {
// Find first non ! char
for (var i=0; i<line.length; i++) {
if (line.substr(i, 1) != "!") {
break;
}
}
var desc = line.substring(i);
// Remove WikiLinks
desc = desc.replace(/\[\[/g, "");
desc = desc.replace(/\]\]/g, "");
text += line.substr(0, i).replace(/[!]/g, '*');
text += '<html><a href="javascript:;" onClick="window.scrollToHeading(\'' + title + '\', \'' + desc+ '\', event)">' + desc+ '</a></html>\n';
}
}
}
wikify(text, span);
}
}
window.scrollToTop = function(evt) {
if (! evt)
var evt = window.event;
var target = resolveTarget(evt);
var tiddler = story.findContainingTiddler(target);
if (! tiddler)
return false;
window.scrollTo(0, ensureVisible(tiddler));
return false;
}
window.scrollToHeading = function(title, anchorName, evt) {
var tiddler = null;
if (! evt)
var evt = window.event;
if (title) {
story.displayTiddler(store.getTiddler(title), title, null, false);
tiddler = document.getElementById(story.idPrefix + title);
} else {
var target = resolveTarget(evt);
tiddler = story.findContainingTiddler(target);
}
if (tiddler == null)
return false;
var children1 = tiddler.getElementsByTagName("h1");
var children2 = tiddler.getElementsByTagName("h2");
var children3 = tiddler.getElementsByTagName("h3");
var children4 = tiddler.getElementsByTagName("h4");
var children5 = tiddler.getElementsByTagName("h5");
var children = new Array();
children = children.concat(children1, children2, children3, children4, children5);
for (var i = 0; i < children.length; i++) {
for (var j = 0; j < children[i].length; j++) {
var heading = children[i][j].innerHTML;
// Remove all HTML tags
while (heading.indexOf("<") >= 0) {
heading = heading.substring(0, heading.indexOf("<")) + heading.substring(heading.indexOf(">") + 1);
}
// Cut off the code added in showtoc for TOP
heading = heading.substr(0, heading.length-6);
if (heading == anchorName) {
var y = findPosY(children[i][j]);
window.scrollTo(0,y);
return false;
}
}
}
return false
}
//}}}
/***
|Name|TiddlerToCPlugin|
|Source|[[FND's DevPad|http://devpad.tiddlyspot.com/#TiddlerToCPlugin]]|
|Version|0.7|
|Author|FND|
|Contributors|[[Saq|http://tw.lewcid.org]]|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|N/A|
|Overrides|N/A|
|Description|create a table of contents from a tiddler's headings|
!Notes
Doug Compton has written a similar, though much more advanced plugin for this purpose, called [[DcTableOfContentsPlugin|http://devpad.tiddlyspot.com/#DcTableOfContentsPlugin]].
!Usage
Add {{{<<ToC>>}}} to the desired tiddler(s). Alternatively, a parameter can be used to display the table of contents for another tiddler: {{{<<ToC "tiddlerName">>}}}.
The styling can be modified in the [[StyleSheetTableOfContents]] shadow tiddler.
<<ToC>>
!Changelog
!!v0.5a (2007-05-20)
* initial release
!!v0.5b (2007-05-20)
* renamed to TiddlerToCPlugin (to prevent confusion with the existing [[TableOfContentsPlugin|http://tiddlytools.com/#TableOfContentsPlugin]])
!!v0.6 (2007-05-21)
* several bugfixes and significant improvements regarding the macro code (thanks Saq)
!!v0.7 (2007-08-29)
* fixed error for tiddlers not containing any headings
!Issues / To Do
* add links to sections (problematic, as there are no anchors, yet?)
* introduce thresholds (minimum amount of headings to show a ToC, maximum depth)
!Code
***/
//{{{
/*
** Styles (can be customized in the StyleSheetTableOfContents shadow tiddler)
*/
config.shadowTiddlers.StyleSheetTableOfContents = "/*{{{*/\n"
+ ".ToC {\n\tfloat: left; /* auto-width */\n\tmargin: 0 2em 2em 0;\n\tborder: 1px solid #aaa;\n\tpadding: 5px;\n\tbackground-color: #eee;\n}\n\n"
+ ".ToC ol {\n\tmargin: 0 1em;\n}\n\n"
+ "h1 {\n\tclear: left;\n}\n"
+ "/*}}}*/";
store.addNotification("StyleSheetTableOfContents", refreshStyles);
/*
** Macro Code
*/
config.macros.ToC = { label: "Add Table of Contents", prompt: "Add Table of Contents" }; // DEBUG: obsolete?
config.macros.ToC.handler =
function(place, macroName, params, wikifier, paramString, tiddler) {
// process parameters
if (params[0]) { // tiddler name
tiddler = store.getTiddler(params[0]);
}
// create table of contents
generateToC(place, tiddler);
return false; // DEBUG: ?
}
/*
** Main Code
*/
generateToC = function(place, tiddler) {
// retrieve headings
var RegEx = /^!+(.*)$/gim;
var tiddlerContents = tiddler.text.match(RegEx);
// create ToC
if(tiddlerContents) {
var ToC = "";
for(var i = 0; i < tiddlerContents.length; i++) {
ToC += tiddlerContents[i] + "\n";
}
// replace headings markup with list markup
for(var i = 0; i < 6; i++) { // DEBUG: inefficient!? (use a single RegEx instead? problem: JavaScript RegEx limitations)
ToC = ToC.replace(/^(#*)!/gim, "$1#");
}
// add ToC wrapper container
ToC = "{{ToC{\n''Table of Contents''\n" + ToC + "}}}\n";
// add ToC to tiddler
wikify(ToC, place);
}
return false;
}
//}}}
<html>
<form action="handle/upload.php" method="post">
<h1>Create HTML file </h1>
Filename :
<input id="ccHTMLname" class="ccHMLname" name="ccHTMLname" /><br/>
add your HTML code to the textbox below :<br/>
<input type="textbox" id="ccHTML" class="ccHML" name="ccHTML" rows="20" cols="100"/><br/>
<input id="username" class="username" type="hidden" name="username" value="admin"/><br/>
<input id="workspaceName" class="workspaceName" type="hidden" name="workspaceName" value=""/>
Create the file in :<br/>
<input id="user" class="user" type="radio" name="saveTo" value="user"/>
My User Area<br/>
<input id="workspace" class="workspace" type="radio" name="saveTo" value="workspace"/>
Workspace Area<br/>
<input class="button" type="submit" value="Create File "/>
</form>
</html>
//(ripped from [[alpha/smmFFImport|http://wiki.osmosoft.com/alpha/smmFFImport]])//
Osmosoft is the open source innovation arm of [[BT|http://www.bt.com/]]. We're a small team of techies that have a passion for open source software, with our main focus being on the TiddlyWiki product.
We have an [[Osmosoft twitter feed|http://www.twitter.com/Osmosoft]] and a [[video channel on Vimeo|http://www.vimeo.com/channel7726]].
!Meet the team
You can follow our work by subscribing to our individual blogs or, if you prefer, read just [[the Osmosoft-related blog entries|The Osmosoft chatter]].
|[img[Jeremy|images/photo_jeremy.jpg]]|''[[Jeremy Ruston]]'' [[jermolene.wordpress.com|http://jermolene.wordpress.com]] [[flickr.com/photos/jermy|http://flickr.com/photos/jermy/]][[twitter.com/jermolene|http://twitter.com/jermolene/]] |
|[img[Andrew|images/photo_andrew.jpg]]|''[[Andrew Back]]'' [[carrierdetect.com|http://carrierdetect.com]] [[flickr.com/photos/carrierdetect/|http://flickr.com/photos/carrierdetect/]][[twitter.com/9600|http://twitter.com/9600/]] |
|[img[Frederik|images/photo_fnd.jpg]]|''[[Frederik Dohr]]'' [[fnd.lewcid.org/blog|http://fnd.lewcid.org/blog/]][[twitter.com/fnd|http://twitter.com/fnd/]] |
|[img[James|images/photo_james.jpg]]|''[[James Shi]]''[[curiousjames.wordpress.com|http://curiousjames.wordpress.com]][[flickr.com/photos/jamesshi/|http://www.flickr.com/photos/jamesshi/]][[twitter.com/dr1ft3r|http://twitter.com/dr1ft3r]]|
|[img[Jon|images/photo_jon.jpg]]|''[[Jon Lister]]'' [[jayfresh.wordpress.com|http://jayfresh.wordpress.com]][[flickr.com/photos/jayfresh/|http://www.flickr.com/photos/jayfresh/]][[twitter.com/jayfresh|http://twitter.com/jayfresh/]] |
|[img[Martin|images/photo_martin.jpg]]|''[[Martin Budden]]'' [[martinswiki.com|http://martinswiki.com]] |
|[img[Nick|images/photo_nick.jpg]]|''[[Nick Webb]]'' [[erraticmusings.com|http://www.erraticmusings.com]][[flickr.com/photos/nickwebb/|http://www.flickr.com/photos/nickwebb/]][[twitter.com/nickwebb|http://twitter.com/nickwebb]] |
|[img[Paul|images/photo_paul.jpg]]|''[[Paul Downey]]'' [[blog.whatfettle.com|http://blog.whatfettle.com]] [[flickr.com/photos/psd|http://flickr.com/photos/psd/]][[twitter.com/psd|http://twitter.com/psd/]] |
|[img[Phil H|images/photo_philh.jpg]]|''[[Phil Hawksworth]]'' [[www.hawksworx.com|http://www.hawksworx.com]][[flickr.com/photos/philhawksworth|http://flickr.com/photos/philhawksworth/]][[twitter.com/philhawksworth|http://twitter.com/philhawksworth/]] |
|[img[Phil W|images/photo_philw.jpg]]|''[[Phil Whitehouse]]'' [[philwhitehouse.blogspot.com|http://philwhitehouse.blogspot.com]] [[flickr.com/photos/philliecasablanca|http://flickr.com/photos/philliecasablanca/]][[twitter.com/casablanca|http://twitter.com/casablanca/]] |
|[img[Simon|images/photo_simon.jpg]]|''[[Simon McManus]]'' [[simonmcmanus.com|http://simonmcmanus.com]] [[flickr.com/photos/simonmcmanus/|http://www.flickr.com/photos/simonmcmanus/]][[twitter.com/simonmcmanus|http://twitter.com/simonmcmanus/]] |
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|3.9.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|config.macros.importTiddlers.handler|
|Options|##Configuration|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Automatically add tags to imported tiddlers so they are easy to find later on. Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<importTiddlers inline>>
<<<
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[LoadTiddlersPlugin]] and [[ExternalTiddlersPlugin]]''
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, "patch" functions that provide backward-compatibility with TW2.1.x and earlier have been split into a separate [[ImportTiddlersPluginPatch]] tiddler to reduce installation overhead for //this// plugin. You only need to install the additional plugin tiddler when using ImportTiddlersPlugin in documents using TW2.1.x or earlier.
* As of 3/21/2007, the interactive {{{<<importTiddlers>>}}} and non-interactive {{{<<loadTiddlers>>}}} macro definitions and related code have been split into separate [[ImportTiddlersPlugin]] and [[LoadTiddlersPlugin]] to permit selective installation of either the interactive and/or non-interactive macro functions.
* Quick Installation Tip: If you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.
<<<
!!!!!Revisions
<<<
2008.04.13 [3.9.0] added 'apply to all' checkbox for collision processing
2008.03.26 [3.8.0] added support for selecting pre-defined systemServer URLs
2008.03.25 [3.7.0] added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
// // ''MACRO DEFINITION''
//{{{
// Version
version.extensions.importTiddlers = {major: 3, minor: 9, revision: 0, date: new Date(2008,4,13)};
// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;
// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;
// default shadow definition
config.shadowTiddlers.ImportTiddlers="<<importTiddlers inline>>";
merge(config.macros.importTiddlers,{
label: "import tiddlers",
prompt: "Copy tiddlers from another document",
openMsg: "Opening %0",
openErrMsg: "Could not open %0 - error=%1",
readMsg: "Read %0 bytes from %1",
foundMsg: "Found %0 tiddlers in %1",
countMsg: "%0 tiddlers selected for import",
processedMsg: "Processed %0 tiddlers",
importedMsg: "Imported %0 of %1 tiddlers from %2",
loadText: "please load a document...",
closeText: "close", // text for close button when file is loaded
doneText: "done", // text for close button when file is not loaded
local: true, // default to import from local file
src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)
proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)
useProxy: false, // use specific proxy script in front of remote URL
inbound: null, // hash-indexed array of tiddlers from other document
newTags: "", // text of tags added to imported tiddlers
addTags: true, // add new tags to imported tiddlers
listsize: 8, // # of lines to show in imported tiddler list
importTags: true, // include tags from remote source document when importing a tiddler
keepTags: true, // retain existing tags when replacing a tiddler
sync: false, // add 'server' fields to imported tiddlers (for sync function)
lastAction: null, // most recent collision button performed
index: 0, // current processing index in import list
sort: "" // sort order for imported tiddler listbox
});
if (config.macros.importTiddlers.coreHandler==undefined)
config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
if (config.macros.importTiddlers.coreHandler)
config.macros.importTiddlers.coreHandler.apply(this,arguments);
else
createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
}
else if (params[0]=='link') { // show link to floating panel
var label=params[1]?params[1]:this.label;
var prompt=params[2]?params[2]:this.prompt;
createTiddlyButton(place,label,prompt,onClickImportMenu);
}
else if (params[0]=='inline') {// show panel as INLINE tiddler content
createImportPanel(place);
document.getElementById("importPanel").style.position="static";
document.getElementById("importPanel").style.display="block";
}
else if (config.macros.loadTiddlers)
config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
if (!e) var e = window.event;
var parent=resolveTarget(e).parentNode;
var panel = document.getElementById("importPanel");
if (panel==undefined || panel.parentNode!=parent)
panel=createImportPanel(parent);
var isOpen = panel.style.display=="block";
if(config.options.chkAnimate)
anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
else
panel.style.display = isOpen ? "none" : "block" ;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
// // Create control panel: HTML, CSS
//{{{
function createImportPanel(place) {
var panel=document.getElementById("importPanel");
if (panel) { panel.parentNode.removeChild(panel); }
setStylesheet(config.macros.importTiddlers.css,"importTiddlers");
panel=createTiddlyElement(place,"span","importPanel",null,null)
panel.innerHTML=config.macros.importTiddlers.html;
refreshImportList();
var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
document.getElementById("importSourceURL").value=siteURL;
config.macros.importTiddlers.src=siteURL;
var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
document.getElementById("importSiteProxy").value=siteProxy;
config.macros.importTiddlers.proxy=siteProxy;
return panel;
}
//}}}
// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\
#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:24%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\
';
//}}}
// // HTML
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
import from\
<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
onClick="config.macros.importTiddlers.local=true;\
document.getElementById(\'importLocalPanel\').style.display=\'block\';\
document.getElementById(\'importHTTPPanel\').style.display=\'none\'"> local file\
<input type="radio" class="rad" name="importFrom" id="importFromWeb" value="http"\
onClick="config.macros.importTiddlers.local=false;\
document.getElementById(\'importLocalPanel\').style.display=\'none\';\
document.getElementById(\'importHTTPPanel\').style.display=\'block\'"> web server\
</td><td align=right>\
<input type=checkbox class="chk" id="chkImportReport" checked\
onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
<!-- import from local file -->\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\
enter source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
onKeyUp="config.macros.importTiddlers.src=this.value"\
onChange="config.macros.importTiddlers.src=this.value;document.getElementById(\'importLoad\').onclick()">\
</div><!--panel-->\
\
<!-- import from http server -->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\
<table><tr><td align=left>\
enter source URL or <a href="javascript:;" id="importSelectFeed"\
onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
select a server</a><br>\
</td><td align=right>\
<input type="checkbox" class="chk" id="importUseProxy"\
onClick="config.macros.importTiddlers.useProxy=this.checked;\
document.getElementById(\'importSiteProxy\').style.display=this.checked?\'block\':\'none\'"> use a proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
onKeyUp="config.macros.importTiddlers.proxy=this.value"\
onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
onKeyUp="config.macros.importTiddlers.src=this.value"\
onChange="config.macros.importTiddlers.src=this.value;">\
</div><!--panel-->\
\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
onclick="onClickImportButton(this)" title="select all tiddlers">\
all </a>\
<a href="javascript:;" id="importSelectNew"\
onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\
added </a> \
<a href="javascript:;" id="importSelectChanges"\
onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\
changes </a> \
<a href="javascript:;" id="importSelectDifferences"\
onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\
differences </a> \
<!--<a href="javascript:;" id="importToggleFilter"\
onclick="onClickImportButton(this)" title="show/hide selection filter">\
filter </a>--> \
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
onclick="onClickImportButton(this)" title="reduce list size">\
– </a>\
<a href="javascript:;" id="importListLarger"\
onclick="onClickImportButton(this)" title="increase list size">\
+ </a>\
<a href="javascript:;" id="importListMaximize"\
onclick="onClickImportButton(this)" title="maximize/restore list size">\
= </a>\
</td></tr></table>\
<select id="importList" size=8 multiple\
onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="margin-bottom:2px;padding-bottom:2px;border-bottom:1px solid #999">\
<input type=checkbox class="chk" id="chkSync" \
onClick="config.macros.importTiddlers.sync=this.checked;">link tiddlers to source document (for synchronizing later)\
</div>\
<input type=checkbox class="chk" id="chkAddTags" checked\
onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \
<input type=checkbox class="chk" id="chkImportTags" checked\
onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \
<input type=checkbox class="chk" id="chkKeepTags" checked\
onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\
<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\
<div align=center style="margin-top:2px">\
<input type=button id="importLoad" class="importButton" style="width:32%" value="load"\
title="load listbox with tiddlers from source document"\
onclick="onClickImportButton(this)">\
<input type=button id="importStart" class="importButton" style="width:32%" value="import"\
title="add selected source tiddlers to the current document"\
onclick="onClickImportButton(this)">\
<input type=button id="importClose" class="importButton" style="width:32%" value="close"\
title="clear listbox or hide control panel"\
onclick="onClickImportButton(this)">\
</div>\
<div id="importCollisionPanel" style="text-align:left;border-top:1px solid #999">\
<table style="border:0;padding:0;margin:0;"><tr valign="bottom" style="border:0;padding:0;margin:0;">\
<td align=left style="border:0;padding:0;margin:0;">\
tiddler already exists:\
</td><td align=right style="border:0;padding:0;margin:0;">\
<input type=checkbox class="chk" id="importApplyToAll" checked> apply to all\
</td></tr></table>\
<input type=text id="importNewTitle" size=15 autocomplete=off">\
<div align=center>\
<input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\
title="do not import this tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importRename" class="importButton" style="width:23%" value="rename"\
title="rename the incoming tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\
title="append the incoming tiddler to the existing tiddler"\
onclick="onClickImportButton(this)">\
<input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\
title="discard the existing tiddler"\
onclick="onClickImportButton(this)">\
</div>\
</div>\
';
//}}}
// // Control interactions
//{{{
function onClickImportButton(which,event)
{
// DEBUG alert(which.id);
var theList = document.getElementById('importList');
if (!theList) return;
var thePanel = document.getElementById('importPanel');
var theCollisionPanel = document.getElementById('importCollisionPanel');
var theNewTitle = document.getElementById('importNewTitle');
var count=0;
switch (which.id)
{
case 'fileImportSource':
case 'importLoad': // load import source into hidden frame
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
if (config.macros.importTiddlers.src=="") break;
// Load document, read it's DOM and fill the list
config.macros.importTiddlers.loadRemoteFile(config.macros.importTiddlers.src,
function(success,params,txt,src,xhr) {
var src=src.replace(/ /g," ");
if (!success) { displayMessage(config.macros.importTiddlers.openErrMsg.format([src,xhr.status])); return; }
var tiddlers = config.macros.importTiddlers.readTiddlersFromHTML(txt);
var count=tiddlers?tiddlers.length:0;
var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
displayMessage(config.macros.importTiddlers.foundMsg.format([count,src]));
config.macros.importTiddlers.inbound=tiddlers;
window.refreshImportList(0);
});
break;
case 'importSelectFeed': // select a pre-defined systemServer feed URL
var p=Popup.create(which); if (!p) return;
var tids=store.getTaggedTiddlers('systemServer');
if (!tids.length)
createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
for (var t=0; t<tids.length; t++) {
var u=store.getTiddlerSlice(tids[t].title,"URL");
var d=store.getTiddlerSlice(tids[t].title,"Description");
if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,"description");
if (!d||!d.length) d=u;
createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
function(){
var u=this.getAttribute('url');
document.getElementById('importSourceURL').value=u;
config.macros.importTiddlers.src=u;
document.getElementById('importLoad').onclick();
},
null,null,null,{url:u});
}
Popup.show(p,false);
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return(false);
// create popup with feed list
// onselect, insert feed URL into input field.
break;
case 'importSelectAll': // select all tiddler list items (i.e., not headings)
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
if (theList.options[t].value=="") continue;
theList.options[t].selected=true;
count++;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectNew': // select tiddlers not in current document
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers
importReport(); // if an import was in progress, generate a report
for (var t=0,count=0; t < theList.options.length; t++) {
theList.options[t].selected=false;
if (theList.options[t].value=="") continue;
if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }
for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler
{ var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }
theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler
count+=theList.options[t].selected?1:0;
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
break;
case 'importToggleFilter': // show/hide filter
case 'importFilter': // apply filter
alert("coming soon!");
break;
case 'importStart': // initiate the import processing
importReport(); // if an import was in progress, generate a report
document.getElementById('importApplyToAll').checked=false;
config.macros.importTiddlers.index=0;
config.macros.importTiddlers.index=importTiddlers(0);
importStopped();
break;
case 'importClose': // unload imported tiddlers or hide the import control panel
// if imported tiddlers not loaded, close the import control panel
if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }
importReport(); // if an import was in progress, generate a report
config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer
refreshImportList(); // reset/resize the listbox
break;
case 'importSkip': // don't import the tiddler
config.macros.importTiddlers.lastAction=which;
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status='skipped after asking'; // mark item as skipped
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item
importStopped();
break;
case 'importRename': // change name of imported tiddler
config.macros.importTiddlers.lastAction=which;
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
theImported.status = 'renamed from '+theImported.title; // mark item as renamed
theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title
theItem.value = theNewTitle.value; // change the listbox item text
theItem.text = theNewTitle.value; // change the listbox item text
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importMerge': // join existing and imported tiddler content
config.macros.importTiddlers.lastAction=which;
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
var theText = theExisting.text+'\n----\n^^merged from: ';
theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\n';
theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
var theDate = new Date();
var theTags = theExisting.getTags()+' '+theImported.getTags();
theImported.set(null,theText,null,theDate,theTags);
theImported.status = 'merged with '+theExisting.title; // mark item as merged
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item
importStopped();
break;
case 'importReplace': // substitute imported tiddler for existing tiddler
config.macros.importTiddlers.lastAction=which;
var theItem = theList.options[config.macros.importTiddlers.index];
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;
var theImported = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(theItem.value);
theImported.status = 'replaces '+theExisting.title; // mark item for replace
theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
theImported.status += ' by '+theExisting.modifier;
theCollisionPanel.style.display='none';
config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item
importStopped();
break;
case 'importListSmaller': // decrease current listbox size, minimum=5
if (theList.options.length==1) break;
theList.size-=(theList.size>5)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListLarger': // increase current listbox size, maximum=number of items in list
if (theList.options.length==1) break;
theList.size+=(theList.size<theList.options.length)?1:0;
config.macros.importTiddlers.listsize=theList.size;
break;
case 'importListMaximize': // toggle listbox size between current and maximum
if (theList.options.length==1) break;
theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;
break;
}
}
//}}}
// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
var theList = document.getElementById("importList");
if (!theList) return;
// if nothing to show, reset list content and size
if (!config.macros.importTiddlers.inbound)
{
while (theList.length > 0) { theList.options[0] = null; }
theList.options[0]=new Option(config.macros.importTiddlers.loadText,"",false,false);
theList.size=config.macros.importTiddlers.listsize;
document.getElementById('importLoad').disabled=false;
document.getElementById('fileImportSource').disabled=false;
document.getElementById('importFromFile').disabled=false;
document.getElementById('importFromWeb').disabled=false;
document.getElementById('importClose').value=config.macros.importTiddlers.closeText;
return;
}
// get the sort order
if (!selectedIndex) selectedIndex=0;
if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading
if (selectedIndex==1) config.macros.importTiddlers.sort='title';
if (selectedIndex==2) config.macros.importTiddlers.sort='modified';
if (selectedIndex==3) config.macros.importTiddlers.sort='tags';
if (selectedIndex>3) {
// display selected tiddler count
for (var t=0,count=0; t < theList.options.length; t++) {
if (!theList.options[t].selected) continue;
if (theList.options[t].value!="")
count+=1;
else { // if heading is selected, deselect it, and then select and count all in section
theList.options[t].selected=false;
for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
theList.options[t].selected=true;
count++;
}
}
}
clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));
return; // no refresh needed
}
// there are inbound tiddlers loaded... disable inapplicable controls...
document.getElementById('importLoad').disabled=true;
document.getElementById('fileImportSource').disabled=true;
document.getElementById('importFromFile').disabled=true;
document.getElementById('importFromWeb').disabled=true;
document.getElementById('importClose').value=config.macros.importTiddlers.doneText;
// get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)
var tiddlers=config.macros.importTiddlers.inbound;
tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
// clear current list contents
while (theList.length > 0) { theList.options[0] = null; }
// add heading and control items to list
var i=0;
var indent=String.fromCharCode(160)+String.fromCharCode(160);
theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);
theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);
// output the tiddler list
switch(config.macros.importTiddlers.sort)
{
case "title":
for(var t = 0; t < tiddlers.length; t++)
theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
break;
case "modified":
// sort descending for newest date first
tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
var lastSection = "";
for(var t = 0; t < tiddlers.length; t++) {
var tiddler = tiddlers[t];
var theSection = tiddler.modified.toLocaleDateString();
if (theSection != lastSection) {
theList.options[i++] = new Option(theSection,"",false,false);
lastSection = theSection;
}
theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
}
break;
case "tags":
var theTitles = {}; // all tiddler titles, hash indexed by tag value
var theTags = new Array();
for(var t=0; t<tiddlers.length; t++) {
var title=tiddlers[t].title;
var tags=tiddlers[t].tags;
if (!tags || !tags.length) {
if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
theTitles["untagged"].push(title);
}
else for(var s=0; s<tags.length; s++) {
if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
theTitles[tags[s]].push(title);
}
}
theTags.sort();
for(var tagindex=0; tagindex<theTags.length; tagindex++) {
var theTag=theTags[tagindex];
theList.options[i++]=new Option(theTag,"",false,false);
for(var t=0; t<theTitles[theTag].length; t++)
theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
}
break;
}
theList.selectedIndex=selectedIndex; // select current control item
if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;
if (theList.size>theList.options.length) theList.size=theList.options.length;
}
//}}}
// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
if (!config.macros.importTiddlers.inbound) return -1;
var theList = document.getElementById('importList');
if (!theList) return;
var t;
// if starting new import, reset import status flags
if (startIndex==0)
for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)
config.macros.importTiddlers.inbound[t].status="";
for (var i=startIndex; i<theList.options.length; i++)
{
// if list item is not selected or is a heading (i.e., has no value), skip it
if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))
continue;
for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)
if (config.macros.importTiddlers.inbound[j].title==t) break;
var inbound = config.macros.importTiddlers.inbound[j];
var theExisting = store.getTiddler(inbound.title);
// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
if (inbound.status=="added")
continue;
// don't import the "ImportedTiddlers" history from the other document...
if (inbound.title=='ImportedTiddlers')
continue;
// if tiddler exists and import not marked for replace or merge, stop importing
if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
return i;
// assemble tags (remote + existing + added)
var newTags = "";
if (config.macros.importTiddlers.importTags)
newTags+=inbound.getTags() // import remote tags
if (config.macros.importTiddlers.keepTags && theExisting)
newTags+=" "+theExisting.getTags(); // keep existing tags
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newTags+=" "+config.macros.importTiddlers.newTags; // add new tags
inbound.set(null,null,null,null,newTags.trim());
// set the status to 'added' (if not already set by the 'ask the user' UI)
inbound.status=(inbound.status=="")?'added':inbound.status;
// set sync fields
if (config.macros.importTiddlers.sync) {
if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
inbound.fields["server.page.revision"]=inbound.modified.convertToYYYYMMDDHHMM();
inbound.fields["server.type"]="file";
inbound.fields["server.host"]=(config.macros.importTiddlers.local?"file://":"")+config.macros.importTiddlers.src;
}
// do the import!
store.suspendNotifications();
store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
store.resumeNotifications();
}
return(-1); // signals that we really finished the entire list
}
//}}}
//{{{
function importStopped()
{
var theList = document.getElementById('importList');
var theNewTitle = document.getElementById('importNewTitle');
if (!theList) return;
if (config.macros.importTiddlers.index==-1)
importReport(); // import finished... generate the report
else {
// import collision...
// show the collision panel and set the title edit field
document.getElementById('importCollisionPanel').style.display='block';
theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;
if (document.getElementById('importApplyToAll').checked
&& config.macros.importTiddlers.lastAction
&& config.macros.importTiddlers.lastAction.id!="importRename") {
onClickImportButton(config.macros.importTiddlers.lastAction);
}
}
}
//}}}
// // ''REPORT GENERATOR''
//{{{
function importReport(quiet)
{
if (!config.macros.importTiddlers.inbound) return;
// DEBUG alert('importReport: start');
// if import was not completed, the collision panel will still be open... close it now.
var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';
// get the alphasorted list of tiddlers
var tiddlers = config.macros.importTiddlers.inbound;
// gather the statistics
var count=0; var total=0;
for (var t=0; t<tiddlers.length; t++) {
if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
if (tiddlers[t].status.substr(0,7)!="skipped") count++;
total++;
}
// generate a report
if (total) displayMessage(config.macros.importTiddlers.processedMsg.format([total]));
if (count && config.options.chkImportReport) {
// get/create the report tiddler
var theReport = store.getTiddler('ImportedTiddlers');
if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }
// format the report content
var now = new Date();
var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\n";
if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)
newText += "imported tiddlers were tagged with: \""+config.macros.importTiddlers.newTags+"\"\n";
newText += "<<<\n";
for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
newText += "<<<\n";
// update the ImportedTiddlers content and show the tiddler
theReport.text = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
theReport.modifier = config.options.txtUserName;
theReport.modified = new Date();
store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }
}
// reset status flags
for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";
// mark document as dirty and let display update as needed
if (count) { store.setDirty(true); store.notifyAll(); }
// always show final message when tiddlers were actually loaded
if (count) displayMessage(config.macros.importTiddlers.importedMsg.format([count,tiddlers.length,config.macros.importTiddlers.src.replace(/ /g," ")]));
}
//}}}
// // File and XMLHttpRequest I/O
//{{{
config.macros.importTiddlers.fileExists=function(theFile) {
var found=false;
// DEBUG: alert('testing fileExists('+theFile+')...');
if(window.Components) {
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
catch(e) { return false; } // security access denied
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
try { file.initWithPath(theFile); }
catch(e) { return false; } // invalid directory
found = file.exists();
}
else { // use ActiveX FSO object for MSIE
var fso = new ActiveXObject("Scripting.FileSystemObject");
found = fso.FileExists(theFile)
}
// DEBUG: alert(theFile+" "+(found?"exists":"not found"));
return found;
}
config.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet) {
if (src==undefined || !src.length) return null; // filename is required
if (!quiet) clearMessage();
if (!quiet) displayMessage(this.openMsg.format([src.replace(/ /g," ")]));
if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if src is relative (i.e., not a URL)
if (!this.fileExists(src)) { // if file cannot be found, might be relative path.. try fixup
var pathPrefix=document.location.href; // get current document path and trim off filename
var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\");
if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
src=pathPrefix+src;
if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
}
}
if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
var txt=loadFile(src);
if ((txt==null)||(txt==false)) // file didn't load
{ if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/ /g," "),"(filesystem error)"])); }
else {
if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/ /g," ")]));
if (callback) callback(true,quiet,convertUTF8ToUnicode(txt),src,null);
}
}
else {
var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
var xhr=doHttp("GET",src,null,null,name,pass,callback,quiet,null)
if (!quiet && !xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
}
}
config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
var remoteStore=new TiddlyWiki();
remoteStore.importTiddlyWiki(html);
return remoteStore.getTiddlers("title");
}
//}}}
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|3.9.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for ImportTiddlersPlugin|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles. Automatically add tags to imported tiddlers so they are easy to find later on. Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Usage
<<<
{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}
invokes the built-in importTiddlers macro (TW2.1.x+). If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)
{{{<<importTiddlers link label tooltip>>}}}
The ''link'' keyword creates an "import tiddlers" link that when clicked to show/hide import control panel. ''label'' and ''tooltip'' are optional text parameters (enclosed in quotes or {{{[[...]]}}}, and allow you to override the default display text for the link and the mouseover help text, respectively.
{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content
<<importTiddlers inline>>
Press ''[browse]'' to select a TiddlyWiki document file to import, and then press ''[open]''. Alternatively, you can type in the path/filename or a remote document URL (starting with http://). When you have entered the desired source location, press ''[load]'' to retrieve the tiddlers from the remote source. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//
Select one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.
''select: all, new, changes, or differences''
You can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:
>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document
>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)
''Import Tagging:''
Tiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.
''Skip, Rename, Merge, or Replace:''
When importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.
To bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.
//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//
''Import Report History''
When tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.
When the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.
If a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.
Note: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.
<<<
!!!!!Revisions
<<<
2008.04.13 [3.9.0] added 'apply to all' checkbox for collision processing
2008.03.26 [3.8.0] added support for selecting pre-defined systemServer URLs
2008.03.25 [3.7.0] added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
2008.01.03 [3.6.0] in loadRemoteFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.10.30 [3.5.6] update [[ImportTiddlers]] shadow tiddler definition to include "inline" link, so the plugin control panel is displayed instead of the standard core interface.
2007.06.27 [3.5.5] added missing 'fields' params to saveTiddler() calls. Fixes problem where importing tiddlers would lose the custom fields. Also, moved functions for backward-compatibility with TW2.1.x to separate [[ImportTiddlersPluginPatch2.1.x]] tiddler, reducing the size of //this// plugin tiddler by a significant amount.
2007.06.25 [3.5.4] added calls to store.suspendNotifications() and store.resumeNotifications(). Eliminates redisplay processing overhead DURING import activities
2007.04.29 [3.5.3] if refreshImportList() when inbound tiddlers are loaded, change "close" button to "done", and disable certain controls to creates a modal condition, so that actions that reload tiddlers cannot be performed unless "done" is first pressed to end the mode..
2007.04.28 [3.5.2] in handler(), added param support for custom link label/prompt
2007.04.19 [3.5.1] in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content. Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.03.22 [3.5.0] in refreshImportList(), add handling for 'select section' when a heading is selected. Makes it really easy to import by tag or date!
2007.03.21 [3.4.0] split loadTiddlers functionality into separate plugin (see [[LoadTiddlersPlugin]])
2007.03.20 [3.3.1] tweak to previous change to allow relative file references via http: (bypasses getLocalPath() so remote URL will be used)
2007.03.20 [3.3.0] added support for local, relative file references: in loadRemoteFile(), check for fileExists(). If not found, prepend relative path location and try again. Allows use of simple "foo.html" file references with importTiddlers and/or loadTiddlers macros
2007.02.24 [3.2.1] re-labeled control panel "open" button to "load" to avoid confusion with "open" button in system-provided Browse... dialog. (i.e., "browse, open, open" becomes "browse, open, load")
2007.02.09 [3.2.0] loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)
2007.02.08 [3.1.3] loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)
2006.11.14 [3.1.2] fix macro handler parameter declaration (double-pasted param list corrupts IE)
2006.11.13 [3.1.1] use apply() method to invoke hijacked core handler
2006.11.13 [3.1.0] hijack TW2.1 built-in importTiddlers.handler() so it can co-exist with the plugin interface 'panel'. Use macro without params (or use 'core' keyword) to display built-in core interface. Use new "link" param to embed "import tiddlers" link that shows floating panel when clicked. Renamed a few plugin utility functions so they don't collide with core internal functions. More