Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
Installation et customization new BidiXTW site.
Announce of new BidiXTW : It's BidiXTW version 5 !
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
<<viewPalette>>
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<div macro="showWhenExists EditPanelTemplate">[[EditPanelTemplate]]</div>
<div class='editor' macro='edit text'></div>
<!--}}}-->
<<search>>
<<closeAll>>
<<newTiddler tag:News >>
<<newJournal title:'0DD/0MM/YYYY' label: "nouveau journal" tag:Changes tag:excludeLists>>
----
<<saveChanges>>
<<uploadToHome>>
<html><a href=download.php class='button'>download</a></html>
----
<<changeMode Reader>>
{{isdirty{<<tiddler IsDirty>>}}}<<changeMode Author>>
<<changeMode>>
Author : <<option txtUserName>>
<!--{{{-->
<div id='header' class='header'>
<div id='topMenu' refresh='content' tiddler='TopMenu'></div>
<div class='siteTitle'>
<span refresh='content' tiddler='IsDirty'></span>
<span refresh='content' tiddler='SiteTitle'></span>
</div>
<div class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></div>
</div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='AuthorMenu'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='AuthorSidebarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<<tabs txtMainTab "Chrono" "Affichage chronologique des éléments utilisateur" UserTabTimeline "Alpha" "Liste aphabétique des éléments utilisateur" TabUser "Index" "Liste des index utilisateur" UserTabTags>>
[[CommunStyleSheet]]
/*{{{*/
body {
margin: 0 30px 0 30px;
}
#sidebarTabs {
font-size: .8em;
line-height: 1em;
}
/*}}}*/
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title'>
<span class='title' macro='view title'></span>
<!--<span macro="miniTag">--></span>
</div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[DD MMM YYYY]]'></span>)</div>
<div class='tagged' macro='tags'></div>
<div class='tagClear'></div>
<div class='viewer' macro='view text wikified'></div>
<div macro="showWhenTagged [[systemList]]">
<div class='viewer' macro="listByTag '' created ''"></div>
</div>
<div class='tagging' macro='tagging'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
|''Name:''|AutoWeavePlugin|
|''Description:''|Automatically adds brackets to nonwikiwords on saving a tiddler.|
|''Version:''|0.1 (March 09, 2007)|
|''Source:''|http://weave.tiddlyspot.com/index.html#AutoWeavePlugin|
|''Author:''|laurence man|
|''[[License]]:''|[[BSD open source license]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Tested on: Firefox 2.0; InternetExplorer 6.0|
|''Patched:''|*Don't AutoWeave tiddlers tagged 'admin' <br>*changes [[excludeLists]] by [[admin]] in selected tiddlers<br>*don't AutoWeave when in adminMode|
!Description
Inspired by [[this|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/93b8de752492ddc4/b0608ebb1149578c]] post on the tiddlywiki google group, and with helpful comments by Eric Shulman, this plugin automatically adds enclosing double brackets to nonwikiwords (i.e., auto linking them) on saving a tiddler. This does not affect the usual autolinking of wikiword tiddler titles.
A nonwikiword tiddler title will be double bracketed if it is found in the tiddler text, and if the title does not have any letters or numbers around it.
!Usage
By default only the first occurrence of each nonwikiword title in the text is auto-bracketed. To bracket all occurrences, change the following line in the below code:
{{{
var replaceOnlyFirst = false;
}}}
to
{{{
var replaceOnlyFirst = false;
}}}
You can also specify a list of tiddler titles that you do not want to be auto-bracketed. By default, the name of the tiddler containing the titles to exclude is called {{{noAutoLink}}}. That name can be specified by changing the following line in the code below:
{{{
var excludeThese = "noAutoLink";
}}}
to
{{{
var excludeThese = "whatever you want";
}}}
In your "noAutoTag" tiddler, each line should contain only one tiddler title to exclude from auto-bracketing. Don't add any spaces on that line unless they are in the tiddler title itself. For example:
{{{
montypython
xmas list - 2007
culture of capitalism - notes
}}}
!Problems/Limitations/Notes
* Can't handle tiddler titles with square brackets in them so they're ignored.
* Can choose to autolink only first occurrence of title, but if you edit the tiddler later and add that title into the tiddler text before the first occurrence of the title, it will be bracketed.
* Shadowed tiddlers and tiddlers tagged with "[[excludeLists]]" are not auto-bracketed.
!Code
***/
//{{{
TiddlyWiki.prototype.saveTiddler_weaveLinks =
TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler =
function(title,newTitle,newBody,modifier,modified,tags)
{
/*
* BidiX : if mode = admin, no AutoWeave
*/
if ((config.macros.changeMode) && (config.macros.changeMode.currentMode == '') )
return this.saveTiddler_weaveLinks.apply(this, arguments);
// User settings
var replaceOnlyFirst = true;
var excludeThese = "noAutoLink";
// Don't tag the list of tiddler titles to exclude.
if (title == excludeThese)
return this.saveTiddler_weaveLinks.apply(this, arguments);
var tagArray = tags.readBracketedList();
if (tagArray && tagArray.contains('admin'))
return this.saveTiddler_weaveLinks.apply(this, arguments);
// Helpers
// ------------------------------------------------------------------------
// To sort titles into descending length.
var compareDescLen = function(a, b)
{
if (a.length == b.length) return 0;
return b.length - a.length;
}
var isBounded = function(start, end)
// [[Test]] if tiddler title has a non-alphanum char (or nothing) on each side.
// Takes both indices of the title match, along with the title itself.
{
var reAlphaNum = new RegExp("\[\A-Za-z0-9\]");
return !(start != 0 && reAlphaNum.test(newBody.substr(start - 1, 1)) ||
end != newBody.length - 1 &&
reAlphaNum.test( newBody.substr(end + 1, 1)));
}
var isBracketed = function(start, end)
// Is matched string within given indices enclosed in pairs of brackets?
// Assumes brackets aren't allowed in titles (even tiddler text);
// bumping into pair of non-enclosing brackets means string isn't enclosed.
{
var foundL = false;
var foundR = false;
// Start from char just before title up to second char in newBody.
for (var i = start - 1; i > 0; i--)
{
if (newBody.charAt(i) == ']' && newBody.charAt(i - 1) == ']')
return false;
if (newBody.charAt(i) == '[' && newBody.charAt(i - 1) == '[')
{
foundL = true;
break;
}
}
// Look from next char after title up to second last char.
for (var i = end + 1; i < newBody.length - 1; i++)
{
if (newBody.charAt(i) == '[' && newBody.charAt(i + 1) == '[')
return false;
if (newBody.charAt(i) == ']' && newBody.charAt(i + 1) == ']')
{
foundR = true;
break;
}
}
return foundL && foundR;
}
var isNonWikiWord = function(word)
// No brackets though they're allowed in tiddler titles.
{
return (word.indexOf(" ") != -1 ||
word.search(config.textPrimitives.wikiLink) == -1) &&
word.indexOf("[") == -1 &&
word.indexOf("]") == -1;
}
var isUsrExcluded = function(currTitle)
// Checks given tiddler title against those in the excluded list.
{
if (excludeArr)
{
for(var i = 0; i < excludeArr.length; i++)
if (excludeArr[i] == currTitle) return true;
}
return false;
}
// var tids = store.getTiddlers("title","excludeLists");
var tids = store.getTiddlers("title","admin");
var arr = new Array(tids.length); // Titles to use: to be filtered, sorted.
var arrLen = 0; // Number of titles.
var matchIdx; // Index of a matching title.
var searchIdx; // Searching from this index in newBody.
var excludeArr;
var titlesToExclude = store.getTiddlerText(excludeThese);
// split(/\n/) might not be ok with IE?
if (titlesToExclude) excludeArr = titlesToExclude.split('\n');
// Filter list of titles.
for (var i = 0; i < arr.length; i++)
{
if (isNonWikiWord(tids[i].title) && !isUsrExcluded(tids[i].title))
{
arr[arrLen] = tids[i].title;
arrLen++;
}
}
arr.sort(compareDescLen);
// Main loop
for (var i = 0; i < arrLen; i++)
{
searchIdx = 0; // Start search for title at start of newBody.
// If a match, replace if not bracketed and if it is free of alphanum
// on either side. Search again from end of matching title in newBody.
// Should maybe rewrite this using regexp.exec.
for ( ; ;)
{
matchIdx = newBody.indexOf(arr[i], searchIdx);
if (matchIdx == -1) break;
var brackets = isBracketed(matchIdx, matchIdx + arr[i].length - 1);
if (brackets && replaceOnlyFirst) break;
if (isBounded(matchIdx, matchIdx + arr[i].length - 1, arr[i])
&& !brackets)
{
newBody = newBody.substring(0, matchIdx) +
"[[" + arr[i] + "]]" +
newBody.substring(matchIdx + arr[i].length);
if (replaceOnlyFirst) break;
}
searchIdx = matchIdx + arr[i].length + 1;
}
}
return this.saveTiddler_weaveLinks.apply(this, arguments);
}
//}}}
<<tiddler BSDOpenSourceLicense>>
Copyright (c) 2005-2008, BidiX (http://BidiX.info)
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*Neither the name of BidiX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
From ages we are looking for a method to manage backup files and I had something like this (http://groups.google.com/group/TiddlyWiki/msg/d8e5d0d6be082ada?hl=en&) on my TodoList for more than a year !
I've now coded a method in [[store.php]] that maintains the size of the backup directory on the web server near a constant size.
Here is how it works. In store.php each time a new backup file is stored, the backup directory is scanned for files with the same prefix as the uploaded file and it holds only :
*the last file of each preceding month,
*the last file for each preceding week of the current month
*the last file for each preceding day of the current week
*the last file for each preceding hour of the current day
*all the file of the current hour
Without the files of the current hour, the number of files in the backup directory for the last year is less than 24 + 7 + 5 + 12 = 48. With an average of 1Mo per backup file, the size of the backup folder should never reach 50 Mo for the last year and 12 Mo more for each previous year.
|''URL:''|http://tiddlyhome.bidix.info/systemServer/basicContent.html|
|''Description:''|Repository for BidiX's basicContent|
|''Author:''|BidiX|
Contact : [[BidiX @ bidix . info|mailto:BidiX@BidiX.info]]
URL : [[BidiX.info|http://BidiX.info/]]
Donation : [[Donation via Paypal|https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=BidiX%40bidix%2einfo&item_name=TiddlyWikiHacking%20Donations&item_number=Donations&no_shipping=2&no_note=1&tax=0¤cy_code=EUR&bn=PP%2dDonationsBF&charset=UTF%2d8]]
<<rssReader asHtml http://tiddlywiki.bidix.info/index.xml>>
The vertical used for BidiX's sites has been upgraded to NewsWiki Version 1.2.0.
To learn more on NewsWiki visit http://TiddlyHome.bidix.info/NewsWiki or in french http://TiddlyHome.bidix.info/NewsWikiFR
Comments and suggestions are welcome.
|''URL:''|http://tiddlywiki.bidix.info/|
|''Description:''|Repository for BidiX's TiddlyWiki Extensions|
|''Author:''|BidiX|
<<rssReader asHtml http://news.com.com/2547-1_3-0-20.xml>>
/***
''Name:'' CalendarPlugin
''Version:'' <<getversion calendar>> (<<getversiondate calendar "DD MMM YYYY">>)
''Author:'' SteveRumsby
''Configuration:''
|''First day of week:''|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|
''Syntax:''
|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|
|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|
|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|
|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|
|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|
***/
// //Modify this section to change the text displayed for the month and day names, to a different language for example. You can also change the format of the tiddler names linked to from each date, and the colours used.
// // ''[[Changes]] by ELS 2005.10.30:''
// // config.macros.calendar.handler()
// // ^^use "tbody" element for IE compatibility^^
// // ^^IE returns 2005 for current year, FF returns 105... fix year adjustment accordingly^^
// // createCalendarDays()
// // ^^use showDate() function (if defined) to render autostyled date with linked popup^^
// // calendar stylesheet definition
// // ^^use .calendar class-specific selectors, add text centering and margin settings^^
//{{{
config.macros.calendar = {};
config.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];
config.macros.calendar.weekendbg = "#c0c0c0";
config.macros.calendar.monthbg = "#e0e0e0";
config.macros.calendar.holidaybg = "#ffc0c0";
//}}}
// //''Code section:''
// (you should not need to alter anything below here)//
//{{{
if(config.options.txtCalFirstDay == undefined)
config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
config.options.txtCalStartOfWeekend = 5;
config.macros.calendar.tiddlerformat = "0DD/0MM/YYYY"; // This used to be changeable - for now, it isn't// <<smiley :-(>>
version.extensions.calendar = { major: 0, minor: 6, revision: 0, date: new Date(2006, 1, 22)};
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
//}}}
// //Is the given date a holiday?
//{{{
function calendarIsHoliday(date)
{
var longHoliday = date.formatString("0DD/0MM/YYYY");
var shortHoliday = date.formatString("0DD/0MM");
for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday) {
return true;
}
}
return false;
}
//}}}
// //The main entry point - the macro handler.
// //Decide what sort of calendar we are creating (month or year, and which month or year)
// // Create the main calendar container and pass that to sub-ordinate functions to create the structure.
// ELS 2005.10.30: added creation and use of "tbody" for IE compatibility and fixup for year >1900//
// ELS 2005.10.30: fix year calculation for IE's getYear() function (which returns '2005' instead of '105')//
//{{{
config.macros.calendar.handler = function(place,macroName,params)
{
var calendar = createTiddlyElement(place, "table", null, "calendar", null);
var tbody = createTiddlyElement(calendar, "tbody", null, null, null);
var today = new Date();
var year = today.getYear();
if (year<1900) year+=1900;
if (params[0] == "thismonth")
{
cacheReminders(new Date(year, today.getMonth(), 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, today.getMonth());
}
else if (params[0] == "lastmonth") {
var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
}
else if (params[0] == "nextmonth") {
var month = today.getMonth()+1; if (month>11) { month=0; year++; }
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
}
else {
if (params[0]) year = params[0];
if(params[1])
{
cacheReminders(new Date(year, params[1]-1, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, params[1]-1);
}
else
{
cacheReminders(new Date(year, 0, 1, 0, 0), 366);
createCalendarYear(tbody, year);
}
}
window.reminderCacheForCalendar = null;
}
//}}}
//{{{
//This global variable is used to store reminders that have been cached
//while the calendar is being rendered. It will be renulled after the calendar is fully rendered.
window.reminderCacheForCalendar = null;
//}}}
//{{{
function cacheReminders(date, leadtime)
{
if (window.findTiddlersWithReminders == null)
return;
window.reminderCacheForCalendar = {};
var leadtimeHash = [];
leadtimeHash [0] = 0;
leadtimeHash [1] = leadtime;
var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
for(var i = 0; i < t.length; i++) {
//just tag it in the cache, so that when we're drawing days, we can bold this one.
window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"];
}
}
//}}}
//{{{
function createCalendarOneMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarYear(calendar, year)
{
var row;
row = createTiddlyElement(calendar, "tr", null, null, null);
var back = createTiddlyElement(row, "td", null, null, null);
var backHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, year-1);
};
createTiddlyButton(back, "<", "Previous year", backHandler);
back.align = "center";
var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
yearHeader.align = "center";
yearHeader.setAttribute("colSpan", 19);
var fwd = createTiddlyElement(row, "td", null, null, null);
var fwdHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, year+1);
};
createTiddlyButton(fwd, ">", "Next year", fwdHandler);
fwd.align = "center";
createCalendarMonthRow(calendar, year, 0);
createCalendarMonthRow(calendar, year, 3);
createCalendarMonthRow(calendar, year, 6);
createCalendarMonthRow(calendar, year, 9);
}
//}}}
//{{{
function createCalendarMonthRow(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDayHeader(row, 3);
createCalendarDayRows(cal, year, mon);
}
//}}}
//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
var month;
if(nav) {
var back = createTiddlyElement(row, "td", null, null, null);
back.align = "center";
back.style.background = config.macros.calendar.monthbg;
/*
back.setAttribute("colSpan", 2);
var backYearHandler = function() {
var newyear = year-1;
removeChildren(cal);
cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, mon);
};
createTiddlyButton(back, "<<", "Previous year", backYearHandler);
*/
var backMonHandler = function() {
var newyear = year;
var newmon = mon-1;
if(newmon == -1) { newmon = 11; newyear = newyear-1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
};
createTiddlyButton(back, "<", "Previous month", backMonHandler);
month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
// month.setAttribute("colSpan", 3);
month.setAttribute("colSpan", 5);
var fwd = createTiddlyElement(row, "td", null, null, null);
fwd.align = "center";
fwd.style.background = config.macros.calendar.monthbg;
// fwd.setAttribute("colSpan", 2);
var fwdMonHandler = function() {
var newyear = year;
var newmon = mon+1;
if(newmon == 12) { newmon = 0; newyear = newyear+1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
};
createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
/*
var fwdYear = createTiddlyElement(row, "td", null, null, null);
var fwdYearHandler = function() {
var newyear = year+1;
removeChildren(cal);
cacheReminders(new Date(newyear, mon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, mon);
};
createTiddlyButton(fwd, ">>", "Next year", fwdYearHandler);
*/
} else {
month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
month.setAttribute("colSpan", 7);
}
month.align = "center";
month.style.background = config.macros.calendar.monthbg;
}
//}}}
//{{{
function createCalendarDayHeader(row, num)
{
var cell;
for(var i = 0; i < num; i++) {
for(var j = 0; j < 7; j++) {
var d = j + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);
if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
cell.style.background = config.macros.calendar.weekendbg;
}
}
}
//}}}
//{{{
function createCalendarDays(row, col, first, max, year, mon)
{
var i;
for(i = 0; i < col; i++) {
createTiddlyElement(row, "td", null, null, null);
}
var day = first;
for(i = col; i < 7; i++) {
var d = i + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
var daycell = createTiddlyElement(row, "td", null, null, null);
var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);
if(day > 0 && day <= max) {
var celldate = new Date(year, mon, day);
// ELS 2005.10.30: use <<date>> macro's showDate() function to create popup
if (window.showDate) {
showDate(daycell,celldate,"popup","DD","DD-MMM-YYYY",true, isaWeekend);
} else {
if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
var title = celldate.formatString(config.macros.calendar.tiddlerformat);
if(calendarIsHoliday(celldate)) {
daycell.style.background = config.macros.calendar.holidaybg;
}
if(window.findTiddlersWithReminders == null) {
var link = createTiddlyLink(daycell, title, false);
link.appendChild(document.createTextNode(day));
} else {
var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
}
}
}
day++;
}
}
//}}}
// //We've clicked on a day in a calendar - create a suitable pop-up of options.
// //The pop-up should contain:
// // * a link to create a new entry for that date
// // * a link to create a new reminder for that date
// // * an <hr>
// // * the list of reminders for that date
//{{{
function onClickCalendarDate(e)
{
var button = this;
var date = button.getAttribute("title");
var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));
date = dat.formatString(config.macros.calendar.tiddlerformat);
var popup = createTiddlerPopup(this);
popup.appendChild(document.createTextNode(date));
var newReminder = function() {
var t = store.getTiddlers(date);
displayTiddler(null, date, 2, null, null, false, false);
if(t) {
document.getElementById("editorBody" + date).value += "\n<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) +
" year:" + (dat.getYear()+1900) + " title: >>";
} else {
document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) +
" year:" + (dat.getYear()+1900) + " title: >>";
}
};
var link = createTiddlyButton(popup, "New reminder", null, newReminder);
popup.appendChild(document.createElement("hr"));
var t = findTiddlersWithReminders(dat, [0,14], null, 1);
for(var i = 0; i < t.length; i++) {
link = createTiddlyLink(popup, t[i].tiddler, false);
link.appendChild(document.createTextNode(t[i].tiddler));
}
}
//}}}
//{{{
function calendarMaxDays(year, mon)
{
var max = config.macros.calendar.monthdays[mon];
if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
max++;
}
return max;
}
//}}}
//{{{
function createCalendarDayRows(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1 + 7;
var day1 = -first1 + 1;
var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first2 < 0) first2 = first2 + 7;
var day2 = -first2 + 1;
var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first3 < 0) first3 = first3 + 7;
var day3 = -first3 + 1;
var max1 = calendarMaxDays(year, mon);
var max2 = calendarMaxDays(year, mon+1);
var max3 = calendarMaxDays(year, mon+2);
while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
}
}
//}}}
//{{{
function createCalendarDayRowsSingle(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1+ 7;
var day1 = -first1 + 1;
var max1 = calendarMaxDays(year, mon);
while(day1 <= max1) {
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
}
}
//}}}
// //ELS 2005.10.30: added styles
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { font-size:10pt; text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");
//}}}
/***
|''Name:''|ChangeModePlugin|
|''Description:''|Change template and styleSheet|
|''Credits:''|SaqImtiaz for is PresentationPlugin|
|''Version:''|0.0.4|
|''Date:''|Jun 5, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#changeModePlugin|
|''Usage:''|{{{<<changeMode [newMode]>>}}}<br>{{{newMode: if omitted the default mode is applied}}}|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.ChangeModePlugin =
{
major: 0, minor: 0, revision: 4,
date: new Date("Jun 9, 2007"),
source: 'http://tiddlywiki.bidix.info/#ChangeModePlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
// From SaqImtiaz's PresentationPlugin
//---------------------------------------------------
TiddlyWiki.prototype.isTiddler= function (title)
{
return store.tiddlerExists(title) || store.isShadowTiddler(title);
};
TiddlyWiki.prototype.removeNotification = function(title,fn)
{
for (var i=0; i<this.namedNotifications.length; i++)
if((this.namedNotifications[i].name == title) && (this.namedNotifications[i].notify == fn))
this.namedNotifications.splice(i,1);
};
Story.prototype.chooseTemplateForTiddler_core = Story.prototype.chooseTemplateForTiddler;
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
if (!template)
template = DEFAULT_VIEW_TEMPLATE;
var mode = config.macros.changeMode.currentMode;
if (template == DEFAULT_VIEW_TEMPLATE) {
if (store.isTiddler(mode+"ViewTemplate"))
return mode+"ViewTemplate";
} else if (template == DEFAULT_EDIT_TEMPLATE) {
if (store.isTiddler(mode+"EditTemplate"))
return mode+"EditTemplate";
}
return this.chooseTemplateForTiddler_core(title,template);
}
Story.prototype.lewcidrefreshAllTiddlers = function()
{
var place = document.getElementById(this.container);
var e = place.firstChild;
if(!e) return;
this.refreshTiddler(e.getAttribute("tiddler"),null,true);
while((e = e.nextSibling) != null)
this.refreshTiddler(e.getAttribute("tiddler"),null,true);
}
//---------------------------------------------------
// manage different modes
//
// config.macros.changeMode.initMode: the name of the initial Mode
// config.macros.changeMode.readOnlyModes: array containing readOnly mode (no Backstage and readOnly)
//
config.macros.changeMode =
{
currentMode: '', // defaultMode
initMode: 'Reader',
readOnlyModes : ['Reader'],
noBackstage : ['Reader', 'Author'],
singlePageMode: ['Reader', 'Author'],
lingo: {
label: "%0 Mode",
prompt: "Change the current mode to '%0'",
modeName: {
Author: 'Author',
Reader: 'Reader',
'': '(default)'
}
},
handler: function(place,macroName,params) {
var newMode = (params[0] ? params[0]: ""); // default to ''
var newModeName = (this.lingo.modeName[newMode] ? this.lingo.modeName[newMode]: newMode); // default to ''
var label = this.lingo.label.format([newModeName]);
var prompt = this.lingo.prompt.format([newModeName]);
createTiddlyButton(place, label, prompt, function() {config.macros.changeMode.action(newMode);}, null, null, null);
},
action: function(template) {
config.macros.changeMode.applyMode(template);
},
defaults: [
{name: "StyleSheet", notify: refreshStyles},
{name: "PageTemplate", notify: refreshPageTemplate}
],
applyMode: function (newMode) {
var oldMode = this.currentMode;
var oldStyleElement = document.getElementById(oldMode+"StyleSheet");
if (oldStyleElement) {
oldStyleElement.parentNode.removeChild(oldStyleElement);
}
// change Palette
if (store.isTiddler(newMode + 'ColorPalette')) {
var tiddler = new Tiddler('ColorPalette');
tiddler.tags.push('admin');
if (!newMode) {
if (store.isTiddler('defaultColorPalette'))
tiddler.text = store.getTiddlerText('defaultColorPalette');
else
tiddler.text = config.shadowTiddlers['ColorPalette'];
} else {
tiddler.text = store.getTiddlerText(newMode + 'ColorPalette');
}
store.addTiddler(tiddler);
}
for (var i=0; i< this.defaults.length; i++)
{
var name = this.defaults[i]["name"];
var newElement = store.isTiddler(newMode + name) ? newMode + name : name;
store.removeNotification(oldMode + name, this.defaults[i]["notify"]);
store.addNotification(newElement,this.defaults[i]["notify"]);
store.notify(newElement); //just one do blanket notify instead?
}
if (backstage && !backstage.button)
backstage.init();
// change readOnly
if (this.readOnlyModes.indexOf(newMode) == -1) {
readOnly = false;
}
else {
readOnly = true;
}
// change backstage display
if (backstage && backstage.button) {
if (this.noBackstage.indexOf(newMode) == -1) {
backstage.button.style.display = "block";
}
else {
backstage.hide();
backstage.button.style.display = "none";
}
// change singlePageMode
if (this.singlePageMode.indexOf(newMode) == -1) {
config.options.chkSinglePageMode = false;
}
else {
config.options.chkSinglePageMode= true;
}
}
this.currentMode = newMode;
story.lewcidrefreshAllTiddlers ();
// store.refreshPalette();
store.notifyAll();
},
init: function() {
if (!store.isTiddler('defaultColorPalette'))
config.shadowTiddlers['defaultColorPalette'] = config.shadowTiddlers['ColorPalette'];
config.macros.changeMode.applyMode(this.initMode);
}
}
config.paramifiers.mode = {
onconfig: function(mode) {
if (mode == 'false')
config.macros.changeMode.initMode = null;
else
config.macros.changeMode.initMode = mode;
}
};
//}}}
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {
background:[[ColorPalette::Background]];
margin:0 auto;
font-size: 85%;
color: [[ColorPalette::Foreground]];
position: relative;
font-family: Helvetica, Arial, sans-serif;
}
h1,h2,h3,h4,h5 {
font-weight: normal;
padding-left: 0;
color: [[ColorPalette::TertiaryDark]];
background: transparent;
}
h1 {font-size: 1.5em; font-weight: normal;border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2 {font-size: 1.3em; border-bottom:0px;}
h3 {font-size: 1.1em; border-bottom:0px;}
h4 {font-size: 1em;}
h5 {font-size: .9em;}
ul, ul ul, ul ul ul {
list-style-image: url(http://tiddlyhome.bidix.info/_th/images/square.gif) ;
}
a {
color: [[ColorPalette::PrimaryMid]];
}
a:hover {
color: [[ColorPalette::PrimaryMid]];
background:transparent;
border-bottom:1px solid [[ColorPalette::PrimaryMid]];
}
.button {
color: [[ColorPalette::PrimaryMid]];
font-weight:bold;
}
#header {
background: [[ColorPalette::Background]];
padding: 0 0 0 0.4em;
height:1%;
}
.siteTitle {
padding: 1.5em 0 0 0;
font-weight: normal;
font-size: 3em;
color: [[ColorPalette::TertiaryDark]] ;
}
.siteSubtitle {
width: 33em;
padding: 0.3em 0em 0.2em 1em;
font-weight: bold;
font-size: 1em;
background: [[ColorPalette::PrimaryMid]];
color: [[ColorPalette::Background]];
}
#displayArea {
margin-left:0.5em;
margin-right:17.3em;
margin-top:3em;
padding-top:0em;
padding-bottom:10px;
padding-left: 1em;
}
/*}}}*/
/***
!!Sidebar
***/
/*{{{*/
#sidebar {
position:absolute;
width: 14em;
border-left:1px solid [[ColorPalette::TertiaryLight]];
padding-left:15px;
margin-top:0.5em;
font-size:1em;
line-height:1.5em;
font-family: Arial,em sans-serif;
background-color: [[ColorPalette::Background]];
}
#sidebar a {
display: inline;
font-weight: normal;
}
#sidebar h1,#sidebar h2,#sidebar h3,#sidebar h4,#sidebar h5 {
font-weight: normal;
margin-bottom:0em;
}
#sidebar h1 {
margin-left:-0.5em;
margin-bottom:0em;
}
#sidebar hr {
border:0;
border-bottom:1px solid [[ColorPalette::TertiaryLight]];
margin: 1em 0;
margin-left:-0.5em;
}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
/*}}}*/
/***
!!viewer
***/
/*{{{*/
.title {
font-size: 1.5em;
font-weight: normal;
color: [[ColorPalette::TertiaryDark]];
background:transparent;
margin: 0;
margin-bottom: .5em;
padding:0;
}
.viewer {
line-height:1.5em;
}
.tiddler {
padding:0;
margin:0;
padding-bottom:0.5em;
}
.externalLink {font-weight:bold;}
.externalLink:hover {border:none;}
.toolbar { visibility:hidden; }
.selected .toolbar { visibility:visible; }
.tagged, .tagging { float:left; }
.tagged li, .tagging li { display:inline; }
.tagged, .tagging { background:transparent !important; border:0 !important; }
.tagged .button {color: [[ColorPalette::TiertiaryPale]] !important; }
/*}}}*/
/***
!!Editor
***/
/*{{{*/
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
/*}}}*/
/***
!!TopMenu
***/
/*{{{*/
#topMenu {
positon:relative; float:right; display:inline;
margin-left:3em;
margin-top:1em;
padding: 0.8em 0em;
}
#topMenu br {display:none; }
#topMenu a, #topMenu .tiddlyLink, #topMenu .button {
margin:0 1em;
color: [[ColorPalette::Foreground]];
margin-right:0;
margin-left:2em;
font-size: 18px;
font-family: Helvetica, sans-serif;
font-weight: normal;
font-style: normal;
}
#topMenu a:hover, #topMenu .activebutton {
border-bottom:5px
solid [[ColorPalette::PrimaryMid]];
}
.calendar, .calendar table, .calendar th, .calendar tr, .calendar td { font-size:12pt; text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }
/*}}}*/
/*{{{*/
@media print {
#topMenu {display: none ! important;}
}
/*}}}*/
#install [[download.php]] as a file on the webserver in the TiddlyWiki folder. Perhaps near by store.php
#Simply put {{{[[download|download.php?]]}}} in the SideBarOptions of TiddlyWiki*
#download as an attachement in one click on this link when viewed over HTTP
* If it is named index.html else put {{{[[download|download.php?file=yourTW.html]]}}}
----
| Name | Type |Version | Date | Core | Requires |
|[[download.php]] | serverside script | 1.1.1 | 2008-08-22 | | |
|HistoryPlugin | plugin | 1.0.0 | 2008-03-23 | 2.3 | |
|HttpGetMacro | plugin | 2.0.0 | Mar 18, 2007 | 2.2 | |
|IsDirtyPlugin | plugin | 1.0.2 | Apr 30, 2007 | 2.2 | |
|GenerateRssByTagPlugin | plugin | 1.0.3 | May 17, 2007 | 2.2 | |
|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack) | plugin | 1.1.0 | Mar 17, 2007 | 2.2 | |
|[[news.php]] | serverside script | 2.0.1 | May 13, 2007 | | |
|PasswordOptionPlugin | plugin | 1.0.1 | Jan 19, 2007 | 2.2 | |
|[[proxy.php]] | serverside script | 2.2.0 | Aug 3, 2007 | | [[allowedsites.txt]] |
|RSSReaderPlugin | plugin | 1.1.2 | 2008-09-02 | 2.2 | |
|[[store.php]] | serverside script | 1.6.1 | Aug 17, 2007 | | |
|[[storeTiddler.php]] | serverside script | 1.2.1 | 2008-05-06 | | |
|UploadPlugin | plugin | 4.1.4 | 2008-08-11 | 2.2 | PasswordOptionPlugin <<tag UploadService>> |
|UploadTiddlerMacro | plugin | 1.0.0 | 2008-09-30 | 2.2 | UploadTiddlerPlugin <<tag UploadService>> |
|UploadTiddlerPlugin | plugin | 1.2.2 | 2008-09-13 | 2.2 | PasswordOptionPlugin <<tag UploadService>> |
|UploadPluginLingoEN | plugin | 4.1.0 | May 8, 2007 | 2.2 | UploadPlugin |
|UploadPluginLingoFR | plugin | 4.1.0 | May 8, 2007 | 2.2 | UploadPlugin |
|UploadPluginLingoCA*<br>*Thanks to PacoRivière | plugin | 4.1.0 | July 15, 2007 | 2.2 | UploadPlugin |
|UploadToFileMacro | plugin | 2.0.1 | Apr 21, 2007 | 2.2 | UploadPlugin |
|UploadToHomeMacro | plugin | 0.0.2 | Apr 21, 2007 | 2.2 | UploadPlugin |
|--WebDAVSavingPlugin-- | --plugin-- | --0.2.1-- | --Apr 21, 2007-- | --2.2-- |Not maintained : Use SaqImtiaz [[WebDavPlugin|http://trac.tiddlywiki.org/browser/Trunk/contributors/SaqImtiaz/plugins/WebDavPlugin.js]]|
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.6 (2006-09-16)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|© 2005-2006 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description
Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.
''Syntax:''
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].
!Revision history
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features:
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen)
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features:
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs:
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features:
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// ForEachTiddlerPlugin
//============================================================================
//============================================================================
// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {
if (!window.abego) window.abego = {};
version.extensions.ForEachTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006,8,16),
source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
copyright: "Copyright (c) abego Software GmbH, 2005-2006 (www.abego-software.de)"
};
// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
TiddlyWiki.prototype.forEachTiddler = function(callback) {
for(var t in this.tiddlers) {
callback.call(this,t,this.tiddlers[t]);
}
};
}
//============================================================================
// forEachTiddler Macro
//============================================================================
version.extensions.forEachTiddler = {
major: 1, minor: 0, revision: 5, date: new Date(2006,2,5), provider: "http://tiddlywiki.abego-software.de"};
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
config.macros.forEachTiddler = {
// Standard Properties
label: "forEachTiddler",
prompt: "Perform actions on a (sorted) selection of tiddlers",
// actions
actions: {
addToList: {},
write: {}
}
};
// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler
// ---------------------------------------------------------------------------
config.macros.forEachTiddler.getContainingTiddler = function(e) {
while(e && !hasClass(e,"tiddler"))
e = e.parentNode;
var title = e ? e.getAttribute("tiddler") : null;
return title ? store.getTiddler(title) : null;
};
config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);
if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the "in" clause
var tiddlyWikiPath = undefined;
if ((i < params.length) && params[i] == "in") {
i++;
if (i >= params.length) {
this.handleError(place, "TiddlyWiki path expected behind 'in'.");
return;
}
tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the where clause
var whereClause ="true";
if ((i < params.length) && params[i] == "where") {
i++;
whereClause = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the sort stuff
var sortClause = null;
var sortAscending = true;
if ((i < params.length) && params[i] == "sortBy") {
i++;
if (i >= params.length) {
this.handleError(place, "sortClause missing behind 'sortBy'.");
return;
}
sortClause = this.paramEncode(params[i]);
i++;
if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
sortAscending = params[i] == "ascending";
i++;
}
}
// Parse the script
var scriptText = null;
if ((i < params.length) && params[i] == "script") {
i++;
scriptText = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the action.
// When we are already at the end use the default action
var actionName = "addToList";
if (i < params.length) {
if (!config.macros.forEachTiddler.actions[params[i]]) {
this.handleError(place, "Unknown action '"+params[i]+"'.");
return;
} else {
actionName = params[i];
i++;
}
}
// Get the action parameter
// (the parsing is done inside the individual action implementation.)
var actionParameter = params.slice(i);
// --- Processing ------------------------------------------
try {
this.performMacro({
place: place,
inTiddler: tiddler,
whereClause: whereClause,
sortClause: sortClause,
sortAscending: sortAscending,
actionName: actionName,
actionParameter: actionParameter,
scriptText: scriptText,
tiddlyWikiPath: tiddlyWikiPath});
} catch (e) {
this.handleError(place, e);
}
};
// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {
var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);
var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
context["tiddlyWiki"] = tiddlyWiki;
// Get the tiddlers, as defined by the whereClause
var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
context["tiddlers"] = tiddlers;
// Sort the tiddlers, when sorting is required.
if (parameter.sortClause) {
this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
}
return {tiddlers: tiddlers, context: context};
};
// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
return this.getTiddlersAndContext(parameter).tiddlers;
};
// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
//
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
//
// All properties are optional.
// For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
var tiddlersAndContext = this.getTiddlersAndContext(parameter);
// Perform the action
var actionName = parameter.actionName ? parameter.actionName : "addToList";
var action = config.macros.forEachTiddler.actions[actionName];
if (!action) {
this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
return;
}
var actionHandler = action.handler;
actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};
// ---------------------------------------------------------------------------
// The actions
// ---------------------------------------------------------------------------
// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
return;
}
// Perform the action.
var list = document.createElement("ul");
place.appendChild(list);
for (var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var listItem = document.createElement("li");
list.appendChild(listItem);
createTiddlyLink(listItem, tiddler.title, true);
}
};
abego.parseNamedParameter = function(name, parameter, i) {
var beginExpression = null;
if ((i < parameter.length) && parameter[i] == name) {
i++;
if (i >= parameter.length) {
throw "Missing text behind '%0'".format([name]);
}
return config.macros.forEachTiddler.paramEncode(parameter[i]);
}
return null;
}
// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
if (p >= parameter.length) {
this.handleError(place, "Missing expression behind 'write'.");
return;
}
var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
// Parse the "begin" option
var beginExpression = abego.parseNamedParameter("begin", parameter, p);
if (beginExpression !== null)
p += 2;
var endExpression = abego.parseNamedParameter("end", parameter, p);
if (endExpression !== null)
p += 2;
var noneExpression = abego.parseNamedParameter("none", parameter, p);
if (noneExpression !== null)
p += 2;
// Parse the "toFile" option
var filename = null;
var lineSeparator = undefined;
if ((p < parameter.length) && parameter[p] == "toFile") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
return;
}
filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
p++;
if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
return;
}
lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
}
}
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
return;
}
// Perform the action.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
var count = tiddlers.length;
var text = "";
if (count > 0 && beginExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
for (var i = 0; i < count; i++) {
var tiddler = tiddlers[i];
text += func(tiddler, context, count, i);
}
if (count > 0 && endExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);
if (count == 0 && noneExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
if (filename) {
if (lineSeparator !== undefined) {
lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
text = text.replace(/\n/mg,lineSeparator);
}
saveFile(filename, convertUnicodeToUTF8(text));
} else {
var wrapper = createTiddlyElement(place, "span");
wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
}
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
return {
place : placeParam,
whereClause : whereClauseParam,
sortClause : sortClauseParam,
sortAscending : sortAscendingParam,
script : scriptText,
actionName : actionNameParam,
actionParameter : actionParameterParam,
tiddlyWikiPath : tiddlyWikiPathParam,
inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
};
};
// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
if (!idPrefix) {
idPrefix = "store";
}
var lenPrefix = idPrefix.length;
// Read the content of the given file
var content = loadFile(this.getLocalPath(path));
if(content === null) {
throw "TiddlyWiki '"+path+"' not found.";
}
// Locate the storeArea div's
var posOpeningDiv = content.indexOf(startSaveArea);
var posClosingDiv = content.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
throw "File '"+path+"' is not a TiddlyWiki.";
}
var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
// Create a "div" element that contains the storage text
var myStorageDiv = document.createElement("div");
myStorageDiv.innerHTML = storageText;
myStorageDiv.normalize();
// Create all tiddlers in a new TiddlyWiki
// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
var tiddlyWiki = new TiddlyWiki();
var store = myStorageDiv.childNodes;
for(var t = 0; t < store.length; t++) {
var e = store[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
title = e.id.substr(lenPrefix);
if(title && title !== "") {
var tiddler = tiddlyWiki.createTiddler(title);
tiddler.loadFromDiv(e,title);
}
}
tiddlyWiki.dirty = false;
return tiddlyWiki;
};
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
//
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
var script = context["script"];
var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
var fullText = (script ? script+";" : "")+functionText+";theFunction;";
return eval(fullText);
};
// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
var result = [];
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
tiddlyWiki.forEachTiddler(function(title,tiddler) {
if (func(tiddler, context, undefined, undefined)) {
result.push(tiddler);
}
});
return result;
};
// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
var message = "Extra parameter behind '"+actionName+"':";
for (var i = firstUnusedIndex; i < parameter.length; i++) {
message += " "+parameter[i];
}
this.handleError(place, message);
};
// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? -1
: +1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
var result =
(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue)
? 0
: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
? +1
: -1;
return result;
};
// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
// To avoid evaluating the sortClause whenever two items are compared
// we pre-calculate the sortValue for every item in the array and store it in a
// temporary property ("forEachTiddlerSortValue") of the tiddlers.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
var count = tiddlers.length;
var i;
for (i = 0; i < count; i++) {
var tiddler = tiddlers[i];
tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
}
// Do the sorting
tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);
// Delete the temporary property that holds the sortValue.
for (i = 0; i < tiddlers.length; i++) {
delete tiddlers[i].forEachTiddlerSortValue;
}
};
// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
displayMessage(message);
};
// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
var message ="<<"+macroName;
for (var i = 0; i < params.length; i++) {
message += " "+params[i];
}
message += ">>";
displayMessage(message);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};
// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
if (place) {
this.createErrorElement(place, exception);
} else {
throw exception;
}
};
// Internal.
//
// Encodes the given string.
//
// Replaces
// "$))" to ">>"
// "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
var reGTGT = new RegExp("\\$\\)\\)","mg");
var reGT = new RegExp("\\$\\)","mg");
return s.replace(reGTGT, ">>").replace(reGT, ">");
};
// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
//
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
// Remove any location part of the URL
var hashPos = originalPath.indexOf("#");
if(hashPos != -1)
originalPath = originalPath.substr(0,hashPos);
// Convert to a native file format assuming
// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
var localPath;
if(originalPath.charAt(9) == ":") // pc local file
localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(7));
else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
localPath = unescape(originalPath.substr(5));
else // pc network file
localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
return localPath;
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
"forEachTiddler");
//============================================================================
// End of forEachTiddler Macro
//============================================================================
//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
var n = prefix.length;
return (this.length >= n) && (this.slice(0, n) == prefix);
};
//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
var n = suffix.length;
return (this.length >= n) && (this.right(n) == suffix);
};
//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
return this.indexOf(substring) >= 0;
};
//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
for (var i = 0; i < this.length; i++) {
if (this[i] == item) {
return i;
}
}
return -1;
};
//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false.
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
return (this.indexOf(item) >= 0);
};
//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
for(var i = 0; i < items.length; i++) {
if (this.contains(items[i])) {
return true;
}
}
return false;
};
//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
//
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null]
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
for(var i = 0; i < items.length; i++) {
if (!this.contains(items[i])) {
return false;
}
}
return true;
};
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... DOM
/*global document */
// ... TiddlyWiki Core
/*global convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink,
displayMessage, endSaveArea, hasClass, loadFile, saveFile,
startSaveArea, store, wikify */
//}}}
/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
GenerateRssByTagPlugin overwrite the core generateRSS() function. And defines a txtRssTag option : <<option txtRssTag>> to specify the tag to use (defaulted to ''"toRSS"'' ).
Only tiddlers with this specific tag are inluded in the RSSFeed. If no tiddlers are selected then works with the old behaviour. (see ticket #270: http://trac.tiddlywiki.org/tiddlywiki/ticket/270).
Because the generateRSS mechanism should change in TW 2.3 this enhancement should not go in the core .
Hint : You can add {{{<<option txtRssTag>>}}} in AdvancedOptions
/***
|''Name:''|GenerateRssByTagPlugin|
|''Description:''|Only tiddlers with a specific tag are inluded in the RSSFeed. If no tiddlers are selected then works as before. (see ticket #270: http://trac.tiddlywiki.org/tiddlywiki/ticket/270). <br>RssTag: <<option txtRssTag>>|
|''Version:''|1.0.2|
|''Date:''|Apr 20, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#GenerateRssByTagPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.GenerateRssByTagPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 20, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0 (Beta 5)'
};
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.generateRssByTag = function()
{
var s = [];
var d = new Date();
var u = store.getTiddlerText("SiteUrl");
// Assemble the header
s.push("<" + "?xml version=\"1.0\"" + " encoding='UTF-8' " + "?" + ">");
s.push("<rss version=\"2.0\">");
s.push("<channel>");
s.push("<title" + ">" + wikifyPlain("SiteTitle").htmlEncode() + "</title" + ">");
if(u)
s.push("<link>" + u.htmlEncode() + "</link>");
s.push("<description>" + wikifyPlain("SiteSubtitle").htmlEncode() + "</description>");
s.push("<language>en-us</language>");
s.push("<copyright>Copyright " + d.getFullYear() + " " + config.options.txtUserName.htmlEncode() + "</copyright>");
s.push("<pubDate>" + d.toGMTString() + "</pubDate>");
s.push("<lastBuildDate>" + d.toGMTString() + "</lastBuildDate>");
s.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
s.push("<generator>TiddlyWiki " + version.major + "." + version.minor + "." + version.revision + "</generator>");
// The body
var tiddlers;
if (config.options.txtRssTag && store.getTaggedTiddlers(config.options.txtRssTag).length > 0)
tiddlers = store.getTaggedTiddlers(config.options.txtRssTag,"modified");
else
tiddlers = store.getTiddlers("modified","[[excludeLists]]");
var n = config.numRssItems > tiddlers.length ? 0 : tiddlers.length-config.numRssItems;
for (var t=tiddlers.length-1; t>=n; t--)
s.push(tiddlers[t].saveToRss(u));
// And footer
s.push("</channel>");
s.push("</rss>");
// Save it all
return s.join("\n");
};
//
// Initializations
//
bidix.generateRss = generateRss; // backup core version
generateRss = bidix.generateRssByTag; // install new one
config.options.txtRssTag = "toRSS"; // default RssTag. use <<option txtRssTag>> to overwritte
merge(config.optionsDesc,{txtRssTag: "Only tiddlers with this tag will be included in the RSS Feed."});
//}}}
Above are sites allowed to be accessed
----
<<HttpGet "proxy.php?list" html>>
----
This file is a TiddlyWiki. It uses NewsWiki a vertical customization for publication.
This NewsWiki uses 3 modes:
*<<changeMode Reader>>: browse and navigate into the content in readOnly mode.
*<<changeMode Author>>: for managing content (tiddlers, tags and perhaps Menus) and publishing (Save to web) the TiddlyWiki.
*<<changeMode>>: is the default mode when start:safe or plugin errors. This mode has the basic TiddlyWiki presentation and behaviour.
BidiXTW is now hosted at http://TiddlyHome.bidix.info/BidiXTW/. You can setup your own TiddlyHome as explain at http://TiddlyHome.bidix.info/.
!Stay tuned
<<tiddler [[Stay tuned]]>>
/***
| Name|HideWhenPlugin|
| Description|Allows conditional inclusion/exclusion in templates|
| Version|3.0 ($Rev: 1845 $)|
| Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $|
| Source|http://mptw.tiddlyspot.com/#HideWhenPlugin|
| Author|Simon Baird <simon.baird@gmail.com>|
| [[License]]|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.removeElementWhen = function(test,place) {
if (test) {
removeChildren(place);
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}}
});
//}}}
I have extracted HistoryPlugin from [[iplugin.js|http://itw.bidix.info/#iPlugins]], the external file containaing all plugins for [[iTW|http://itw.bidix.info/]], in a stand alone plugin available at http://tiddlywiki.bidix.info/#HistoryPlugin
Enjoy HistoryPlugin
/***
|''Name:''|HistoryPlugin|
|''Description:''|Limits to only one tiddler open. Manages an history stack and provides macro to navigate in this history (<<history>><<back>><<forward>>).|
|''Version:''|1.0.0|
|''Date:''|2008-03-23|
|''Source:''|http://tiddlywiki.bidix.info/#HistoryPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.3.0|
***/
//{{{
Story.prototype.tiddlerHistory = [];
Story.prototype.historyCurrentPos = -1;
Story.prototype.currentTiddler = null;
Story.prototype.maxPos = 11;
Story.prototype.old_history_displayTiddler = Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
title = ((typeof title === "string") ? title : title.title);
//SinglePageMode
if (this.currentTiddler) this.closeTiddler(this.currentTiddler);
if (template == 2) {
//switch to Edit mode : don't manage
story.old_history_displayTiddler(null,title,template,animate,slowly);
return;
}
// if same tiddler no change
if (this.tiddlerHistory[this.historyCurrentPos] == title) {
this.currentTiddler = title;
story.old_history_displayTiddler(null,title,template,animate,slowly);
return;
}
if (this.historyCurrentPos == this.tiddlerHistory.length -1) {
// bottom of stack
this.tiddlerHistory.push(title);
if (this.tiddlerHistory.length > 11) {
this.tiddlerHistory.shift();
} else {
this.historyCurrentPos += 1;
}
} else {
// middle of stack
this.historyCurrentPos += 1;
if (this.tiddlerHistory[this.historyCurrentPos] != title) {
// path change => cut history
this.tiddlerHistory[this.historyCurrentPos] = title;
var a = [];
for(var i = 0; i <= this.historyCurrentPos;i++) {
a[i] = this.tiddlerHistory[i];
}
this.tiddlerHistory = a;
}
}
this.currentTiddler = title;
story.old_history_displayTiddler(null,title,template,animate,true);
scrollTo(0, 1);
}
Story.prototype.old_history_closeTiddler = Story.prototype.closeTiddler;
Story.prototype.closeTiddler = function(title,animate,slowly)
{
this.currentTiddler = null;
story.old_history_closeTiddler.apply(this,arguments);
}
config.macros.history = {};
config.macros.history.action = function(event) {
var popup = Popup.create(this);
if(popup)
{
if (!story.tiddlerHistory.length)
createTiddlyText(popup,"No history");
else
{
var c = story.tiddlerHistory.length;
for (i=0; i<c;i++ )
{
var elmt = createTiddlyElement(popup,"li");
var btn = createTiddlyButton(elmt,story.tiddlerHistory[i],story.tiddlerHistory[i],config.macros.history.onClick);
btn.setAttribute("historyPos",i);
}
}
}
Popup.show(popup,false);
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
config.macros.history.handler = function(place,macroName,params)
{
createTiddlyButton(place, 'history', 'history', config.macros.history.action);
}
config.macros.history.onClick = function(ev)
{
var e = ev ? ev : window.event;
var historyPos = this.getAttribute("historyPos");
story.historyCurrentPos = historyPos -1;
story.displayTiddler(null,story.tiddlerHistory[historyPos]);
return false;
};
config.macros.back = {};
config.macros.back.action = function() {
if (story.historyCurrentPos > 0) {
if (story.currentTiddler) story.closeTiddler(story.currentTiddler);
story.historyCurrentPos = story.historyCurrentPos -2;
story.displayTiddler(null,story.tiddlerHistory[story.historyCurrentPos+1]);
} else {
//if (story.currentTiddler) story.old_history_displayTiddler(null,story.currentTiddler);
};
return false;
}
config.macros.back.handler = function(place,macroName,params)
{
createTiddlyButton(place, '<', 'back', config.macros.back.action,"backButton");
}
config.macros.forward = {};
config.macros.forward.action = function() {
if (story.historyCurrentPos < story.tiddlerHistory.length -1) {
if (story.currentTiddler) story.closeTiddler(story.currentTiddler);
//story.historyCurrentPos = story.historyCurrentPos;
story.displayTiddler(null,story.tiddlerHistory[story.historyCurrentPos+1]);
} else {
//if (story.currentTiddler) story.old_history_displayTiddler(null,story.currentTiddler);
}
return false;
}
config.macros.forward.handler = function(place,macroName,params)
{
createTiddlyButton(place, '>', 'forward', config.macros.forward.action, "ibutton");
}
//}}}
To upload a TiddlyWiki on your web server:
#Import UploadPlugin from BidiXTW aka http://TiddlyWiki.bidix.info/
#Install an UploadService on your web server by configuring this scripts [[store.php]]
#set an {{{<<upload [params]>>}}} button for example in your SideBarOptions with {{{params}}} or UploadOptions as describe in UploadPluginDoc
#click on the <<upload>> button
Or sign at http://TiddlySpot.com/
/***
|''Name:''|HttpGetMacro|
|''Description:''|Submit an HttpGet and display the response|
|''Version:''|2.0.0|
|''Date:''|Mar 18, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#HttpGetMacro|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
config.macros.HttpGet = {
cache: [], // url => responseText
messages: {
401: "%0 unauthorized (HTTP status:401).",
403: "%0 forbidden (HTTP status:403).",
404: "%0 not found (HTTP status:404).",
405: "Method not allowed to access %0 (HTTP status: 405)."
},
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var url = params[0];
var format = params[1];
wikify("^^<<HttpGetUpdate "+url+" [[" + tiddler.title + "]]>>^^\n",place);
var div = createTiddlyElement(place, "div", "HttpGet");
if (this.cache[url]) {
this.display(this.cache[url], format, div);
}
else {
this.get(url, format, div);
}
},
get: function(url, format, place) {
var params = {
format: format,
place: place
};
var r = loadRemoteFile(url,config.macros.HttpGet.display,params);
if (typeof r == "string")
displayMessage(r);
return r;
},
display: function(status,params,responseText,url,xhr) {
if (status) {
if (params['format'] == 'html') {
wikify("<html>"+responseText+"</html>", params['place']);
}
else { //text
wikify(responseText, params['place']);
}
} else {
if (config.macros.HttpGet.messages[xhr.status])
displayMessage(config.macros.HttpGet.messages[xhr.status].format([url]));
else
displayMessage("HTTP Error " + xhr.status + " in accessing " + url);
}
}
};
config.macros.HttpGetUpdate = {
label: "Update",
prompt: "Clear the cache and redisplay this tiddler",
handler: function(place,macroName,params) {
var url = params[0];
var tiddlerTitle = params[1];
createTiddlyButton(place, this.label, this.prompt,
function () {
if (config.macros.HttpGet.cache[url]) {
config.macros.rssReader.cache[url] = null;
}
story.refreshTiddler(tiddlerTitle,null, true);
return false;});
}
};
//}}}
/***
|''Name:''|IsDirtyPlugin|
|''Description:''|When the TiddlyWiki needs to be saved the tiddler named IsDirty contains ' * ' else it is empty. IsDirty tiddler is also appended in front of the browser page title.<br>Hint: Put it in front of your SiteTitle in your PageTemplate or in your MainMenu as an indicator.<br>For now IsDirty: <<tiddler IsDirty>>|
|''Version:''|1.0.1|
|''Date:''|Mar 20, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#IsDirtyPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.IsDirtyPlugin = {
major: 1, minor: 0, revision: 1,
date: new Date("Mar 20, 2007"),
source: 'http://tiddlywiki.bidix.info/#IsDirtyPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.setDirty = TiddlyWiki.prototype.setDirty;
bidix.initIsDirty = function()
{
var tags = "[[excludeLists]] [[excludeSearch]]";
var tiddler = store.getTiddler("IsDirty");
if (!tiddler) {
tiddler = new Tiddler("IsDirty");
//tiddler.set(title,text,modifier,modified,tags,created,fields)
tiddler.set(null,null,null,null,tags,null,null);
store.addTiddler(tiddler);
}
tiddler.set(null,"",null,null,null,null,null);
return tiddler;
};
TiddlyWiki.prototype.setDirty = function(dirty)
{
var indic = " * ";
var oldDirty = this.isDirty ();
bidix.setDirty.apply(this,arguments);
var tiddler = bidix.initIsDirty();
if (dirty)
tiddler.set(null,indic,null,null,null,null,null);
else
tiddler.set(null," ",null,null,null,null,null);
story.refreshTiddler(tiddler.title);
store.notify(tiddler.title, true);
refreshPageTitle();
};
bidix.refreshPageTitle = function()
{
document.title = wikifyPlain("IsDirty") + wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle");
};
bidix.core.refreshPageTitle = refreshPageTitle ;
refreshPageTitle = bidix.refreshPageTitle;
bidix.initIsDirty();
//}}}
<<forEachTiddler
where
'tiddler.tags.contains("toRSS") /*&& tiddler.tags.contains("toRSS")*/'
sortBy
'store.getValue(tiddler,"created")'
descending
write
'"\n@@font-size:1.5em;[["+tiddler.title+"]]@@@@color:#999; - " + Date.convertFromYYYYMMDDHHMM(store.getValue(tiddler,"created")).formatString("YYYY/0MM/0DD")+" - "+tiddler.modifier+"@@\n" +
"{{excerpt{\n" +
(tiddler.text.match("/%%/") ?
tiddler.text.substr(0,tiddler.text.indexOf("/%%/")) :
tiddler.text.substr(0,300)) +
" ...\n[[more ...|"+tiddler.title+"]]\n----\n}}}";'
>>
<<rssReader asText http://www.lemonde.fr/rss/sequence/0,2-3208,1-0,0.xml>>
<<rssReader asHtml http://www.liberation.fr/interactif/rss/actualites/>>
<<tiddler BSDOpenSourceLicense>>
//{{{
//thanks Simon!
Array.prototype.tiddlerList = function(listFormat,max) {
var output = "";
if (!listFormat) listFormat = "'[[' + tiddler.title + ']] - ' + tiddler.created.formatString('0DD/0MM/YY') + ' - ' + tiddler.modifier + '\\n'";
if (!max) var max = this.length;
if (this.length > 0 && this[0] instanceof Tiddler) {
for (var i=0;i<max;i++) {
var tiddler = this[i];
output += eval(listFormat);
}
}
return output;
}
// tag, sorted, listformat, max(0), noReverse(true)
config.macros.listByTag = {};
config.macros.listByTag.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
params[0] = (params[0] ? params[0] : tiddler.title);
var tiddlers = store.getTaggedTiddlers(params[0],params[1]);
if (params[3] == 0) params[3] = null;
if (! params[4])
tiddlers = tiddlers.reverse();
wikify(tiddlers.tiddlerList(params[2],params[3]),place,null,tiddler);
};
//}}}
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
major: 1, minor: 1, revision: 0,
date: new Date("mar 17, 2007"),
source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};
if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};
bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
}
return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
[[home|Welcome]]
[[Index|Doc]]
[[News|toRSS]]
[[Latest news]]
----
<<changeMode Reader>>
{{isdirty{<<tiddler IsDirty>>}}}<<changeMode Author>>
<<changeMode>>
Author : <<option txtUserName>>
----
<<tiddler [[About site]]>>
<style type="text/css">#bidix_copyright {display:none;}</style>
<div id="bidix_copyright">
Welcome to BidiXTW.
BidiXTW is a <a href="http://www.tiddlywiki.com">TiddlyWiki</a> written by <a href="http://bidix.info">BidiX</a> and hosted at <a href="http://tiddlyhome.bidix.info"/>TiddlyHome.bidix.info</a>.
Copyright © 2005-2008 BidiX (http://BidiX.info)
</div>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<link rel="shortcut icon" href="http://TiddlyHome.bidix.info/_th/images/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="icon" href="http://TiddlyHome.bidix.info/_th/images/favicon.ico" type="image/vnd.microsoft.icon" />
<!--}}}-->
When the TiddlyWiki needs to be saved the tiddler named IsDirty contains ' * ' else it is empty. IsDirty tiddler is also appended in front of the browser page title.
Hint: Put it in front of your SiteTitle in your PageTemplate or in your MainMenu as an indicator.
@@Try to edit this tiddler.@@
For now IsDirty: <<tiddler IsDirty>>
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Version|2.0.3|
|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|Slider.prototype.stop|
|Description|Make any tiddler content into an expandable 'slider' panel, without needing to create a separate tiddler to contain the slider content.|
++++!!!!![Configuration]>
Enable animation for slider panels
<<option chkFloatingSlidersAnimate>> allow sliders to animate when opening/closing
>(note: This setting is in //addition// to the general option for enabling/disabling animation effects:
><<option chkAnimate>> enable animations (entire document)
>For slider animation to occur, you must also allow animation in general.
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. You can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created. This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.
Additional optional syntax elements let you specify
*default to open
*cookiename
*heading level
*floater (with optional CSS width value)
*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
<<<
''2007.03.30 - 2.0.3'' added chkFloatingSlidersAnimate (default to FALSE), so that slider animation can be disabled independent of the overall document animation setting (avoids strange rendering and focus problems in floating panels)
''2007.03.01 - 2.0.2'' for TW2.2+, hijack Morpher.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
''2007.03.01 - 2.0.1'' in hijack for Slider.prototype.stop, use apply() to pass params to core function
|please see [[NestedSlidersPluginHistory]] for additional revision details|
''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: 3, date: new Date(2007,3,30)};
//}}}
//{{{
// 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;
if (config.options.chkFloatingSlidersAnimate==undefined) config.options.chkFloatingSlidersAnimate=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
window.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 && (theSlider.className!='floatingPanel' || config.options.chkFloatingSlidersAnimate))
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
else
theSlider.style.display = isOpen ? "none" : "block";
// reset to default width (might have been changed via plugin code)
theSlider.style.width=theSlider.defaultPanelWidth;
// align slider/floater position with target button
if (!isOpen) window.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;
}
// TW2.1 and earlier:
// hijack Slider animation handler 'stop' handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function()
{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }
// TW2.2+
// hijack Morpher animation handler 'stop' handler so overflow is visible after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
Morpher.prototype.coreStop = Morpher.prototype.stop;
Morpher.prototype.stop = function()
{ this.coreStop.apply(this,arguments); 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-15;
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
}
//}}}
Type the text for 'New Tiddler'
Type the text for 'New Tiddler'
!Description
A vertical TiddlyWiki for publishing.
!Features
Version 1.2.0
*mode management
**<<changeMode Reader>>: browse and navigate into the content in readOnly mode and SinglePageMode .
**<<changeMode Author>>: for managing content (tiddlers, tags and perhaps Menus) and publishing (Save to web) the TiddlyWiki.
**<<changeMode>>: is the default mode when start:safe or plugin errors. This mode has the basic TiddlyWiki presentation and behaviour.
*SinglePageMode and ReadOnly for Reader
*StyleSheet reader oriented
*All [[admin]] stuff masked to reader and author
*Tweaks to ease navigation :
**an admin tag for all admin stuff
**Triangle added to tag button to indicate popup
**new lists ('timeline' 'all' 'tags') without tiddlers or tags tagged 'admin'
**[[systemList]]
**[[systemTool]]
**Latest [[News]]
*AutoWeave in Author mode
*Localizable
**See NewsWikiFR
!Components
all tagged NewsWiki :
*ChangeModePlugin
*SinglePageModePlugin
*NewsWikiTweaks
*IsDirtyPlugin
*SinglePageModePlugin
*CalendarPlugin
*AutoWeavePluginPatched
*''[[admin]] tag'' : has the special meanning to hide to Reader and Author
*''[[systemList]]'' : List all tiddlers tagged with it
*''[[systemTool]]'' : in tiddler view, hide subtitle (modifier, created, modified)
*''<mode><tiddler>'' (like AuthorStyleSheet, ReaderStyleSheet, StyleSheet ...)
!Sources
*Sample :
**http://TiddlyHome.bidix.info/
**http://TiddlyHomeFR.bidix.info/
*Empty :
**http://TiddlyHome.bidix.info/systemServer/NewsWiki
**http://TiddlyHome.bidix.info/systemServer/NewsWikiFR
!toDo
*--[[toRelease]]--
*--French version--
*--In French Version, [[locale.fr-FR]] is loaded after NewsWikiTweaks. NewsWikiTweaksFR should require local.fr-FR--
!History
!!2007/06/05
*Version 1.0.0
!!2007/07/28
*Version 1.2.0
|URL:|http://tiddlyhome.bidix.info/systemServer/NewsWiki.html|
|Description|Repository for NewsWiki system ressources |
|Author:|BidiX|
/***
|''Name:''|NewsWikiTweaks|
|''Description:''|Some tweaks for NewsWiki|
|''Version:''|0.0.1|
|''Date:''|Jun 11, 2007|
|''Source:''|http://TiddlyWiki.bidix.info/#NewsWikiTweaks|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
/***
!Options
***/
//{{{
//Options
config.options.chkAnimate = false;
config.options.txtRssTag = 'toRSS';
//}}}
/***
!tag
***/
//{{{
merge(config.views.wikified.tag,{
labelNoTags: "",
labelTags: ""});
/*
merge(config.macros.tagging,{
label: "",
labelNotTag: "",
tooltip: ""});
*/
createTagButton = function(place,tag,excludeTiddler)
{
var triangle = " "+glyph("downTriangle");
var theTag = createTiddlyButton(place,tag+triangle,config.views.wikified.tag.tooltip.format([tag]),onClickTag);
theTag.setAttribute("tag",tag);
if(excludeTiddler)
theTag.setAttribute("tiddler",excludeTiddler);
return theTag;
}
onClickTag = function(e)
{
if(!e) var e = window.event;
var theTarget = resolveTarget(e);
var popup = Popup.create(this);
var tag = this.getAttribute("tag");
var title = this.getAttribute("tiddler");
if(popup && tag) {
var tagged = store.getTaggedTiddlers(tag);
var titles = [];
var li,r;
for(r=0;r<tagged.length;r++) {
if(tagged[r].title != title)
titles.push(tagged[r].title);
}
var lingo = config.views.wikified.tag;
if(titles.length > 0) {
// var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
// openAll.setAttribute("tag",tag);
// createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
for(r=0; r<titles.length; r++) {
createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
}
} else {
createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));
}
createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
if (!config.options.chkSinglePageMode) {
var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
openAll.setAttribute("tag",tag);
}
// createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
createTiddlyText(h,lingo.openTag.format([tag]));
}
Popup.show();
e.cancelBubble = true;
if(e.stopPropagation) e.stopPropagation();
return false;
}
config.macros.tagChooser.onClick = function(e)
{
if(!e) var e = window.event;
var lingo = config.views.editor.tagChooser;
var popup = Popup.create(this);
var tags = store.getTags("[[admin]]");
if(tags.length == 0)
createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);
for(var t=0; t<tags.length; t++) {
var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),config.macros.tagChooser.onTagClick);
theTag.setAttribute("tag",tags[t][0]);
theTag.setAttribute("tiddler",this.getAttribute("tiddler"));
}
Popup.show();
e.cancelBubble = true;
if(e.stopPropagation) e.stopPropagation();
return false;
};
//}}}
/***
!tabs
***/
//{{{
config.macros.list.user= {};
config.macros.list.user.handler = function(params)
{
return store.reverseLookup("tags","admin",false,"title");
};
config.macros.userTimeline = {};
config.macros.userTimeline.handler = function(place,macroName,params)
{
var field = params[0] ? params[0] : "modified";
var tiddlers = store.reverseLookup("tags","admin",false,field);
var lastDay = "";
var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1])) : 0;
for(var t=tiddlers.length-1; t>=last; t--) {
var tiddler = tiddlers[t];
var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
if(theDay != lastDay) {
var theDateList = document.createElement("ul");
place.appendChild(theDateList);
createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(config.macros.timeline.dateFormat));
lastDay = theDay;
}
var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink");
theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
}
};
//}}}
/***
!Shadow tiddlers
***/
//{{{
config.shadowTiddlers.GettingStarted =
"To get started with this blank NewsWiki, you'll need to change mode to <<changeMode Author>> or <<changeMode>>\n\n" +
config.shadowTiddlers.GettingStarted;
//}}}
/***
!others
***/
//{{{
config.macros.version.handler = function(place)
{
createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : "") + (version.build ? " (build #" + version.build + ")" : ""));
};
//}}}
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>>
Password: <<option pasUploadPassword>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations
----
Also see
AdvancedOptions
UploadOptions
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='IsDirty'></span>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='IsDirty'></span>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
PasswordOptionPlugin extends the core Options with a non encrypted password type.
Notice:
*How a style can be specified for a specific option in StyleSheet
----
Test Password: <<option pasPassword myPasOptionInput >>
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
!!Why a ProxyService
When a TiddlyWiki is located on the web (view over http), for security reasons, browsers do not allow TiddlyWiki to access a remote page located on a different site.
For example, when views over http a TiddlyWiki is unable to:
*import a plugin using EricShulman's ImportTiddlersPlugin
*access <<tag RSSFeed>> with RSSReaderPlugin
*imbed a remote page in a tiddler
* ...
A first possibility is to bypass the browser check. However, visitors usually are not comfortable with altering the security options of their browser.
The ProxyService provides an other way.
!!How it works
ProxyService is mainly a ServerSide script that implements a very simple proxy. [[proxy.php]] is a ProxyService.
The command: {{{proxy.php?url=host.domain.com/some/page.html}}} simply gets and returns the content of the url, provided that this access is allowed. The access is allowed :
*to a list of site contained in a separate file
*to hosts of the same domain.
Nevertheless, this service should not be used for other purpose than as TiddlyWiki companion and under the TiddlyWiki owner's control.
!!Installing [[proxy.php]]
#Upload [[proxy.php]] to your site
#Edit and Upload [[allowedsites.txt]]
#Verify your installation. From your tiddlywiki accessed over HTTP go to :
##[[proxy.php?help|proxy.php?help]]
##[[proxy.php?list|proxy.php?list]]
##[[proxy.php?url=http://www.tiddlywiki.com/|proxy.php?url=http://www.tiddlywiki.com/]]
#Optionally, if you can limit access to proxy.php by requesting basic-auth in your .htaccess file.
!!How to setup in TiddlyWiki
In TiddlyWiki viewed over HTTP, provided that a ProxyService is available, for an access to a remote site (for example {{{http://host.domain.com/some/page.html}}}) , you should use the ProxyService (like {{{proxy.php?url=http://host.domain.com/some/page.html}}}).
Fortunately, LoadRemoteFileThroughProxy appends the content of SiteProxy in front of the url used by the core LoadRemoteFile function only when the TiddlyWiki is viewed over http. With this small extension it is possible to use directly ImportTiddlers when TiddlyWiki is viewed over HTTP.
!!
Thanks to UploadToFileMacro, [[allowedsites.txt]] can be maintained in TiddlyWiki by editing [[allowedsites.txt]] and using <<uploadToFile allowedsites.txt allowedsites.txt>> macro.
/***
|''Name:''|RSSReaderPlugin|
|''Description:''|This plugin provides a RSSReader for TiddlyWiki|
|''Version:''|1.1.2|
|''Date:''|2008-09-02|
|''Source:''|http://tiddlywiki.bidix.info/#RSSReaderPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#RSSReaderPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''Credit:''|BramChen for RssNewsMacro|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''OptionalRequires:''|http://www.tiddlytools.com/#NestedSlidersPlugin|
***/
//{{{
version.extensions.RSSReaderPlugin = {
major: 1, minor: 1, revision: 2,
date: new Date("2008-09-02"),
source: "http://TiddlyWiki.bidix.info/#RSSReaderPlugin",
author: "BidiX",
coreVersion: '2.2.0'
};
config.macros.rssReader = {
dateFormat: "DDD, DD MMM YYYY",
itemStyle: "display: block;border: 1px solid black;padding: 5px;margin: 5px;", //useed '@@'+itemStyle+itemText+'@@'
msg:{
permissionDenied: "Permission to read preferences was denied.",
noRSSFeed: "No RSS Feed at this address %0",
urlNotAccessible: " Access to %0 is not allowed"
},
cache: [], // url => XMLHttpRequest.responseXML
desc: "noDesc",
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var desc = params[0];
var feedURL = params[1];
var toFilter = (params[2] ? true : false);
var filterString = (toFilter?(params[2].substr(0,1) == ' '? tiddler.title:params[2]):'');
var place = createTiddlyElement(place, "div", "RSSReader");
wikify("^^<<rssFeedUpdate "+feedURL+" [[" + tiddler.title + "]]>>^^\n",place);
if (this.cache[feedURL]) {
this.displayRssFeed(this.cache[feedURL], feedURL, place, desc, toFilter, filterString);
}
else {
var r = loadRemoteFile(feedURL,config.macros.rssReader.processResponse, [place, desc, toFilter, filterString]);
if (typeof r == "string")
displayMessage(r);
}
},
// callback for loadRemoteFile
// params : [place, desc, toFilter, filterString]
processResponse: function(status, params, responseText, url, xhr) { // feedURL, place, desc, toFilter, filterString) {
if (window.netscape){
try {
if (document.location.protocol.indexOf("http") == -1) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
}
}
catch (e) { displayMessage(e.description?e.description:e.toString()); }
}
if (xhr.status == 404)
{
displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
return;
}
if (!status)
{
displayMessage(config.macros.rssReader.noRSSFeed.format([url]));
return;
}
if (xhr.responseXML) {
// response is interpreted as XML
config.macros.rssReader.cache[url] = xhr.responseXML;
config.macros.rssReader.displayRssFeed(xhr.responseXML, params[0], url, params[1], params[2], params[3]);
}
else {
if (responseText.substr(0,5) == "<?xml") {
// response exists but not return as XML -> try to parse it
var dom = (new DOMParser()).parseFromString(responseText, "text/xml");
if (dom) {
// parsing successful so use it
config.macros.rssReader.cache[url] = dom;
config.macros.rssReader.displayRssFeed(dom, params[0], url, params[1], params[2], params[3]);
return;
}
}
// no XML display as html
wikify("<html>" + responseText + "</html>", params[0]);
displayMessage(config.macros.rssReader.msg.noRSSFeed.format([url]));
}
},
// explore down the DOM tree
displayRssFeed: function(xml, place, feedURL, desc, toFilter, filterString){
// Channel
var chanelNode = xml.getElementsByTagName('channel').item(0);
var chanelTitleElement = (chanelNode ? chanelNode.getElementsByTagName('title').item(0) : null);
var chanelTitle = "";
if ((chanelTitleElement) && (chanelTitleElement.firstChild))
chanelTitle = chanelTitleElement.firstChild.nodeValue;
var chanelLinkElement = (chanelNode ? chanelNode.getElementsByTagName('link').item(0) : null);
var chanelLink = "";
if (chanelLinkElement)
chanelLink = chanelLinkElement.firstChild.nodeValue;
var titleTxt = "!![["+chanelTitle+"|"+chanelLink+"]]\n";
var title = createTiddlyElement(place,"div",null,"ChanelTitle",null);
wikify(titleTxt,title);
// ItemList
var itemList = xml.getElementsByTagName('item');
var article = createTiddlyElement(place,"ul",null,null,null);
var lastDate;
var re;
if (toFilter)
re = new RegExp(filterString.escapeRegExp());
for (var i=0; i<itemList.length; i++){
var titleElm = itemList[i].getElementsByTagName('title').item(0);
var titleText = (titleElm ? titleElm.firstChild.nodeValue : '');
if (toFilter && ! titleText.match(re)) {
continue;
}
var descText = '';
descElem = itemList[i].getElementsByTagName('description').item(0);
if (descElem){
try{
for (var ii=0; ii<descElem.childNodes.length; ii++) {
descText += descElem.childNodes[ii].nodeValue;
}
}
catch(e){}
descText = descText.replace(/<br \/>/g,'\n');
if (desc == "asHtml")
descText = "<html>"+descText+"</html>";
}
var linkElm = itemList[i].getElementsByTagName("link").item(0);
var linkURL = linkElm.firstChild.nodeValue;
var pubElm = itemList[i].getElementsByTagName('pubDate').item(0);
var pubDate;
if (!pubElm) {
pubElm = itemList[i].getElementsByTagName('date').item(0); // for del.icio.us
if (pubElm) {
pubDate = pubElm.firstChild.nodeValue;
pubDate = this.formatDateString(this.dateFormat, pubDate);
}
else {
pubDate = '0';
}
}
else {
pubDate = (pubElm ? pubElm.firstChild.nodeValue : 0);
pubDate = this.formatDate(this.dateFormat, pubDate);
}
titleText = titleText.replace(/\[|\]/g,'');
var rssText = '*'+'[[' + titleText + '|' + linkURL + ']]' + '' ;
if ((desc != "noDesc") && descText){
rssText = rssText.replace(/\n/g,' ');
descText = '@@'+this.itemStyle+descText + '@@\n';
if (version.extensions.nestedSliders){
descText = '+++[...]' + descText + '===';
}
rssText = rssText + descText;
}
var story;
if ((lastDate != pubDate) && ( pubDate != '0')) {
story = createTiddlyElement(article,"li",null,"RSSItem",pubDate);
lastDate = pubDate;
}
else {
lastDate = pubDate;
}
story = createTiddlyElement(article,"div",null,"RSSItem",null);
wikify(rssText,story);
}
},
formatDate: function(template, date){
var dateString = new Date(date);
// template = template.replace(/hh|mm|ss/g,'');
return dateString.formatString(template);
},
formatDateString: function(template, date){
var dateString = new Date(date.substr(0,4), date.substr(5,2) - 1, date.substr(8,2)
);
return dateString.formatString(template);
}
};
config.macros.rssFeedUpdate = {
label: "Update",
prompt: "Clear the cache and redisplay this RssFeed",
handler: function(place,macroName,params) {
var feedURL = params[0];
var tiddlerTitle = params[1];
createTiddlyButton(place, this.label, this.prompt,
function () {
if (config.macros.rssReader.cache[feedURL]) {
config.macros.rssReader.cache[feedURL] = null;
}
story.refreshTiddler(tiddlerTitle,null, true);
return false;});
}
};
//}}}
This plugin provides a RSSReader for TiddlyWiki. If TiddlyWiki is viewed over HTTP, RSSReaderPlugin requires a ProxyService.
See examples : <<tag RSSFeed>>.
See documentation : RSSReaderPluginDoc
if NestedSlidersPlugin is available, item contents are folded.
//last update: RSSReaderPlugin v 1.1.1//
!Description
This plugin provides a RSSReader for TiddlyWiki
* It accesses asynchronously an RSSFeed
*Depending on the chanel item format, each item could be written as :
**simple text wikified
**html
!Usage
{{{
<<rssReader noDesc|asHtml|asText rssUrl ['filtering string']>>
noDesc: only title of item is printed
asHtml: if you know that description contain html (links, img ...),
the text is enclosed with <html> </html> tags
asText: if the description should not be interpreted as html the
description is wikified
rssUrl: the rssFeed url that could be accessed.
'filtering string': if present, the rssfeed item title must contained
this string to be displayed.
If 'filering string' contained space characters only, the tiddler
title is used for filtering.
}}}
For security reasons, if the TiddlyWiki is accessed from http, a ProxyService should be used to access an rssFeed from an other site.
!examples
| !reader | !RSSFeed type | !working from |
| BidiXTWRSS | Description asHtml | file: or tiddlywiki.bidix.info |
| [[Le Monde]] | Description asText | file: or tiddlywiki.bidix.info using proxy |
| YahooNewsSport | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| TiddlyWikiRSS | Description asHtml | file: or tiddlywiki.bidix.info using proxy |
| [[Libération]] | noDesc | file: or tiddlywiki.bidix.info using proxy |
| [[TestComment]] | asText and filters | file: or tiddlywiki.bidix.info using proxy |
see : <<tag RSSFeed>> for the full list.
!Revision history
* V1.1.0 (2207/04/13)
**No more import functions
* V1.0.0 (2006/11/11)
**refactoring using core loadRemoteFile function
**import using new tiddlywiki:tiddler element
**import and presentation preserved without EricShulman's NestedSliderPlugin
**better display of items
* v0.3.0 (24/08/2006)
** Filter on RSS item title
** Place to display redefined for asynchronous processing
* v0.2.2 (22/08/2006)
**Haloscan feed has no pubDate.
* v0.2.1 (08/05/2006)
* v0.2.0 (01/05/2006)
**Small adapations for del.icio.us feed
* v0.1.1 (28/04/2006)
**Bug : Channel without title
* v0.1.0 (24/04/2006)
** initial release
[[news.php]] is an RSSFeed reader. It accesses an RSS 2.0 file and displays the feed in a page using a CSS.
The full syntax is :
>news.php[?[rss=<rssfile>[&css=<cssfile>]]
with :
*<rssfile>: a RSSFeed (default index.xml)
*<cssfile>: a CssFile (default embeded css)
Some examples :
*http://tiddlylab.bidix.info/news.php
*http://tiddlylab.bidix.info/news.php?rss=http://www.tiddlywiki.com/index.xml
*http://tiddlylab.bidix.info/news.php?rss=http://tw.lewcid.org/index.xml
*http://tiddlylab.bidix.info/news.php?rss=http://www.tiddlywiki.com/beta/index.xml&css=news.css (But links are not correct due to http://www.tiddlywiki.com/beta/#SiteUrl )
*http://tiddlylab.bidix.info/news.php?css=news.css
*http://tiddlylab.bidix.info/news.php?rss=http://news.com.com/2547-1_3-0-20.xml
*http://tiddlylab.bidix.info/news.php?rss=http://www.liberation.fr/rss.php
----
Background: #fff
Foreground: #333
PrimaryPale: #FFBFBF
PrimaryLight: #BF2323
PrimaryMid: #BF2323
PrimaryDark: #660000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #ff0000
<<viewPalette>>
<<search>>
[[home|Welcome]]
[[Index|Doc]]
[[News|News]]
[[Latest news]]
----
[[Help]]
<html><a href=download.php class='button'>download</a></html>
<<tiddler IsDirty>><<changeMode Author>>
<<changeMode>>
----
<<tiddler [[Site]]>>
<!--{{{-->
<div id='page'>
<div id='header' class='header'>
<div id='topMenu' refresh='content' tiddler='TopMenu'></div>
<div id='title'>
<div class='siteTitle' refresh='content' tiddler='SiteTitle'></div>
<div class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></div>
</div>
</div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='ReaderMainMenu'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
</div>
<!--}}}-->
[[CommunStyleSheet]]
/***
!!page
***/
/*{{{*/
#page {
border-left: 1px solid [[ColorPalette::TertiaryLight]];
padding: 0 30px 0 30px;
margin-left: auto;
margin-right: auto;
margin-top: 0px;
width: 65em;
position: relative;
text-align: left;
background-color: [[ColorPalette::Background]];
color: [[ColorPalette::Foreground]];
}
/*}}}*/
<!--{{{-->
<div class='title'>
<span class='title' macro='view title'></span>
<!--<span macro="miniTag">--></span>
</div>
</div>
<div macro="hideWhenTaggedAny systemTool systemList">
<span class = "subtitle"><span macro='view created date [[0DD/0MM/YYYY]]'></span> - <span macro='view modifier'></span></span>
<div class='tagged' macro='tags'></div>
<div class='tagClear'></div>
</div>
<div class='viewer' macro='view text wikified'></div>
<div macro="showWhenTagged systemList">
<div class='viewer' macro="listByTag '' created ''"></div>
</div>
<!--}}}-->
/***
|Name|SinglePageModePlugin|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Version|2.2.3|
|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.displayTiddler(), Story.prototype.displayTiddlers()|
|Description|Display tiddlers one at a time with automatic update of URL (permalink). Also, option to always open tiddlers at top of page|
Normally, as you click on the links in TiddlyWiki, more and more tiddlers are displayed on the page. The order of this tiddler display depends upon when and where you have clicked. Some people like this non-linear method of reading the document, while others have reported that when many tiddlers have been opened, it can get somewhat confusing.
!!!!!Usage
<<<
SinglePageMode allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time. When SinglePageMode is enabled, the title of the current tiddler is automatically displayed in the browser window's titlebar and the browser's location URL is updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler.
Even when SinglePageMode is disabled (i.e., displaying multiple tiddlers is permitted), you can reduce the potential for confusion by enable TopOfPageMode, which forces tiddlers to always open at the top of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
When installed, this plugin automatically adds checkboxes in the AdvancedOptions tiddler so you can enable/disable the plugin behavior. For convenience, these checkboxes are also included here:
<<option chkSinglePageMode>> Display one tiddler at a time
<<option chkTopOfPageMode>> Always open tiddlers at the top of the page
<<<
!!!!!Installation
<<<
import (or copy/paste) the following tiddlers into your document:
''SinglePageModePlugin'' (tagged with <<tag [[systemConfig]]>>)
^^documentation and javascript for SinglePageMode handling^^
When installed, this plugin automatically adds checkboxes in the ''shadow'' AdvancedOptions tiddler so you can enable/disable this behavior. However, if you have customized your AdvancedOptions, you will need to ''manually add these checkboxes to your customized tiddler.''
<<<
!!!!!Revision History
<<<
''2007.02.06 [2.2.3]'' in Story.prototype.displayTiddler(), use convertUnicodeToUTF8() for correct I18N string handling when creating URL hash string from tiddler title (based on bug report from BidiX)
''2007.01.08 [2.2.2]'' use apply() to invoke hijacked core functions
''2006.07.04 [2.2.1]'' in hijack for displayTiddlers(), suspend TPM as well as SPM so that DefaultTiddlers displays in the correct order.
''2006.06.01 [2.2.0]'' added chkTopOfPageMode (TPM) handling
''2006.02.04 [2.1.1]'' moved global variable declarations to config.* to avoid FireFox 1.5.0.1 crash bug when assigning to globals
''2005.12.27 [2.1.0]'' hijack displayTiddlers() so that SPM can be suspended during startup while displaying the DefaultTiddlers (or #hash list). Also, corrected initialization for undefined SPM flag to "false", so default behavior is to display multiple tiddlers
''2005.12.27 [2.0.0]'' Update for TW2.0
''2005.11.24 [1.1.2]'' When the back and forward buttons are used, the page now changes to match the URL. Based on code added by Clint Checketts
''2005.10.14 [1.1.1]'' permalink creation now calls encodeTiddlyLink() to handle tiddler titles with spaces in them
''2005.10.14 [1.1.0]'' added automatic setting of window title and location bar ('auto-permalink'). feature suggestion by David Dickens.
''2005.10.09 [1.0.1]'' combined documentation and code in a single tiddler
''2005.08.15 [1.0.0]'' Initial Release
<<<
!!!!!Credits
<<<
This feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]].
Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts
<<<
!!!!!Code
***/
//{{{
version.extensions.SinglePageMode= {major: 2, minor: 2, revision: 3, date: new Date(2007,2,6)};
if (config.options.chkSinglePageMode==undefined) config.options.chkSinglePageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkSinglePageMode>> Display one tiddler at a time";
if (config.options.chkTopOfPageMode==undefined) config.options.chkTopOfPageMode=false;
config.shadowTiddlers.AdvancedOptions += "\n<<option chkTopOfPageMode>> Always open tiddlers at the top of the page";
config.SPMTimer = 0;
config.lastURL = window.location.hash;
function checkLastURL()
{
if (!config.options.chkSinglePageMode)
{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
if (config.lastURL == window.location.hash)
return;
// var tiddlerName = convertUTF8ToUnicode(decodeURI(window.location.hash.substr(1)));
var tiddlerName = decodeURI(window.location.hash.substr(1));
tiddlerName=tiddlerName.replace(/\[\[/,"").replace(/\]\]/,""); // strip any [[ ]] bracketing
if (tiddlerName.length) story.displayTiddler(null,tiddlerName,1,null,null);
}
if (Story.prototype.SPM_coreDisplayTiddler==undefined) Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
{
if (config.options.chkSinglePageMode) {
// window.location.hash = encodeURIComponent(convertUnicodeToUTF8(String.encodeTiddlyLink(title)));
window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
config.lastURL = window.location.hash;
document.title = wikifyPlain("IsDirty") + wikifyPlain("SiteTitle") + " - " + title;
story.closeAllTiddlers();
if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
}
if (config.options.chkTopOfPageMode) { story.closeTiddler(title); window.scrollTo(0,0); srcElement=null; }
this.SPM_coreDisplayTiddler.apply(this,arguments);
}
if (Story.prototype.SPM_coreDisplayTiddlers==undefined) Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
Story.prototype.displayTiddlers = function(srcElement,titles,template,unused1,unused2,animate,slowly)
{
// suspend single-page mode when displaying multiple tiddlers
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
this.SPM_coreDisplayTiddlers.apply(this,arguments);
config.options.chkSinglePageMode=saveSPM; config.options.chkTopOfPageMode=saveTPM;
}
//}}}
Author: BidiX
Vertical : NewsWiki 1.2.0
Motor: TiddlyWiki <<version>>
Repository for ~BidiX's ~TiddlyWiki Extensions
http://tiddlywiki.bidix.info/
*RSS Feed [img[http://www.mozilla.org/images/feed-icon-14x14.png][http://tiddlywiki.bidix.info/index.xml]] : http://tiddlywiki.bidix.info/index.xml
*[[News page|http://tiddlyhome.bidix.info/BidixTW/news.php]] : http://news.bidix.info/
*For comments and suggestion feel free to email to BidiX.
/*{{{*/
.myPasOptionInput {background:[[ColorPalette::SecondaryPale]]; }
/*}}}*/
The Haloscan feed on comments: http://www.haloscan.com/members/rss.php?user=adlister
!!No Filtering :
<<rssReader asText http://www.haloscan.com/members/rss.php?user=adlister>>
!!Filtering on 'Andrew Lister' :
<<rssReader asText http://www.haloscan.com/members/rss.php?user=adlister 'Andrew Lister'>>
!!Filtering on tiddler.title :
<<rssReader asText http://www.haloscan.com/members/rss.php?user=adlister ' '>>
[img[http://tiddlyhome.bidix.info/_th/images/TiddlyHomeLogo.32.jpg][http://tiddlyhome.bidix.info/]] TiddlyHome is a package design as an infrastructure for multi-user and multi-site TiddlyWiki hosting service based on UploadPlugin.
TiddlyHome is in beta stage and uses TiddlyWiki 2.2.
More at http://TiddlyHome.bidix.info/
|owner:|BidiX|
|site:|BidiXTW|
|url:|http://TiddlyWiki.bidix.info/|
|rootUrl:|http://tiddlyhome.bidix.info/|
!Usefull url for your site
*http://TiddlyWiki.bidix.info/backup : List of backup files
*http://TiddlyWiki.bidix.info/download.php : to download thisTiddlyWiki
*http://TiddlyWiki.bidix.info/index.xml : your RSSFeed
*http://TiddlyWiki.bidix.info/news.php : to display your RSSFeed
!Access and change data
*http://tiddlyhome.bidix.info/#Site : Site properties
*http://tiddlyhome.bidix.info/#User : User properties
!More Information on TiddlyHome
*http://tiddlyhome.bidix.info/ for your hosting service
*http://TiddlyHome.bidix.info/ for BidiX's TiddlyHome Package
/***
|''Name:''|TiddlyHomeSetupPlugin|
|''Description:''|Check and setup all components|
|''Version:''|1.0.0|
|''Date:''|Jul 28, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#TiddlyHomeSetupPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|UploadToHomeMacro|
***/
//{{{
version.extensions.TiddlyHomeSetupPlugin = {
major: 1, minor: 0, revision: 0,
date: new Date("Jul 28, 2007"),
source: 'http://tiddlywiki.bidix.info/#TiddlyHomeSetupPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info)',
coreVersion: '2.2.0'
};
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.getParamsFromTiddler = function(tiddlerTitle, sliceNames) {
tiddlerTitle = (tiddlerTitle ? tiddlerTitle:this.messages.homeParamsTiddler);
if (!store.tiddlerExists(tiddlerTitle) && !store.isShadowTiddler(tiddlerTitle)) {
throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([tiddlerTitle]));
}
return sliceValues = store.getTiddlerSlices(tiddlerTitle,sliceNames);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
bidix.checkPlugin('UploadPlugin',4,1,0);
config.macros.upload.authenticateUser = false; // authentication check by .htaccess
// default TiddlyHomeParameters in shadows
// user can overide this
merge(config.shadowTiddlers,{
'TiddlyHomeParameters':[
"|owner:|BidiX|",
"|site:|BidiXTW|",
"|url:|http://TiddlyWiki.bidix.info/|",
"|rootUrl:|http://TiddlyHome.bidix.info/|"
].join("\n")});
// get config from TiddlyHomeParameters
config.tiddlyHome = {};
merge(config.tiddlyHome, bidix.getParamsFromTiddler('TiddlyHomeParameters',['user','site','url','rootUrl']));
// add TiddlyHomeSidebar in SideBarOptions
config.shadowTiddlers.SideBarOptions = config.shadowTiddlers.SideBarOptions.replace(/(<<saveChanges>>)/,
"$1<<tiddler TiddlyHomeSidebar>>");
merge(config.shadowTiddlers,{
// link to favicon.ico
'MarkupPreHead': [
"<!--{{{-->",
"<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>",
"<link rel=\"shortcut icon\"href=\"" +
config.tiddlyHome.rootUrl +
"_th/images/favicon.ico\" type=\"image/vnd.microsoft.icon\" />",
"<link rel=\"icon\" href=\"" +
config.tiddlyHome.rootUrl +
"_th/images/favicon.ico\" type=\"image/vnd.microsoft.icon\" /> ",
"<!--}}}-->"
].join("\n"),
// tweaks to UploadToHomeMacro parameters
'HomeParameters': [
"|UploadUserName:||",
"|UploadStoreUrl:|" + config.tiddlyHome.url + "store.php|",
"|UploadDir:|.|",
"|UploadFilename:|index.html|",
"|UploadBackupDir:|backup|",
"!Usefull url for your site",
"*" + config.tiddlyHome.url + "backup : List of backup files",
"*" + config.tiddlyHome.url + "download.php : to download thisTiddlyWiki",
"*" + config.tiddlyHome.url + "index.xml : your RSSFeed",
"*" + config.tiddlyHome.url + "news.php : to display your RSSFeed",
"!Access and change data",
"*" + config.tiddlyHome.rootUrl + "#Site : Site properties",
"*" + config.tiddlyHome.rootUrl + "#User : User properties",
"!More Information on TiddlyHome",
"*" + config.tiddlyHome.rootUrl + " for your hosting service",
"*http://TiddlyHome.bidix.info/ for BidiX's TiddlyHome Package"
].join("\n"),
'TiddlyHomeSidebar':[
"<<uploadToHome>><html><a href=" +
config.tiddlyHome.url + "download.php class='button'>download</a></html>"
].join("\n")
});
// Options tweaks
//config.options.txtUserName = config.tiddlyHome.user;
//config.options.pasUploadPassword = '';
config.options.txtBackupFolder = "backup";
config.options.chkSaveBackups = true;
config.options.chkAutoSave = false;
config.options.chkRegExpSearch = false;
config.options.chkCaseSensitiveSearch = false;
config.options.chkAnimate = false;
config.options.chkGenerateAnRssFeed = true;
config.options.chkSaveEmptyTemplate = false;
//}}}
|URL:|http://TiddlyHome.bidix.info/systemServer/TiddlyHomeSystem.html|
|Description|Repository for TiddlyHome system ressources |
|Author:|BidiX|
~TiddlyWiki is a powerful [[wiki|http://en.wikipedia.org/wiki/Wiki]] in a single html file which possesses all the features needed to manage and to outline personal notes in an efficient way.
No facility is required. You only need to download an empty ~TiddlyWiki on your desktop to start to use it. It can be stored on USB stick. To send it just attached it to mail. You can also upload it on web server to publish a whole site.
For details visit [[www.TiddlyWiki.com|http://www.tiddlywiki.com]].
^^Version: <<version>>^^
~TiddlyWiki est un puissant [[wiki|http://fr.wikipedia.org/wiki/Wiki]] dans un simple fichier html qui possède toutes les caractéristiques pour gérer et présenter des notes personnelles d'une manière efficace.
Il ne nécessite aucune installation. Il suffit de sauvegarder un ~TiddlyWiki vide sur son bureau-écran pour commencer à l'utiliser. Il peut être copier sur une clé USB. Pour l'envoyer il suffit de le mettre en pièce jointe d'un courriel. En le téléchargeant sur un site web vous publier un site complet.
Pour plus d'information visiter [[www.TiddlyWiki.com|http://www.tiddlywiki.com]].
^^Version: <<version>>^^
<<rssReader asHtml http://www.tiddlywiki.com/index.xml>>
[[Extension directory]] <<tag Domain>><<tag Doc>><<tag Dev>><<tag About>>
UploadPlugin with <<tag UploadService>> extend TiddlyWiki with @@upload@@ and @@save to web@@ commands.
See [[HowToUpload]].
[[Upload]] is :
<<tiddler UploadPluginDoc>>
This form upload any file with an UploadService describe in [[Upload]]
----
<html><center>
<form enctype="multipart/form-data" action="store.php" method="post" target="_blank">
<input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
This file : <input name="userfile" type="file" /><p>
Options* : <input type="text" name="UploadPlugin" size=80 value="backupDir=BACKUP_DIR;uploaddir=UPLOAD_DIR;user=UPLOAD_USER;password=UPLOAD_PASSWORD;debug=0;" /><p>
<input type="submit" value="Upload" />
</form></center>
</html>
----
* Substitute BACKUP_DIR, UPLOAD_DIR, UPLOAD_USER and UPLOAD_PASSWORD with your values. See UploadPlugin for option details.
For security reason, don't save your password in a tiddler.
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 22/08/2008 11:04:56 | BidiX | [[/|http://tiddlywiki.bidix.info/#download.php]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup |
| 02/09/2008 22:25:33 | BidiX | [[/|http://tiddlywiki.bidix.info/#RSSReaderPlugin]] | [[store.php|http://tiddlywiki.bidix.info/store.php]] | . | [[index.html | http://tiddlywiki.bidix.info/index.html]] | |
| 02/09/2008 22:25:57 | BidiX | [[/|http://tiddlywiki.bidix.info/#RSSReaderPlugin]] | [[store.php|http://tiddlywiki.bidix.info/store.php]] | . | [[index.html | http://tiddlywiki.bidix.info/index.html]] | backup |
| 13/09/2008 20:11:48 | BidiX | [[/|http://tiddlywiki.bidix.info/#UploadTiddler]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup | ok |
| 13/09/2008 20:13:47 | BidiX | [[/|http://tiddlywiki.bidix.info/#UploadTiddler]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup |
| 13/09/2008 21:53:38 | BidiX | [[/|http://tiddlywiki.bidix.info/#UploadTiddlerPlugin]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup |
| 30/09/2008 23:20:55 | BidiX | [[/|http://tiddlywiki.bidix.info/#%5B%5BExtension%20directory%5D%5D]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup |
| 30/09/2008 23:21:35 | BidiX | [[/|http://tiddlywiki.bidix.info/#%5B%5BExtension%20directory%5D%5D]] | [[store.php|http://tiddlywiki.bidix.info/store.php]] | . | [[index.html | http://tiddlywiki.bidix.info/index.html]] | |
| 30/09/2008 23:21:50 | BidiX | [[/|http://tiddlywiki.bidix.info/#%5B%5BExtension%20directory%5D%5D]] | [[store.php|http://tiddlywiki.bidix.info/store.php]] | . | [[index.html | http://tiddlywiki.bidix.info/index.html]] | | ok |
| 30/09/2008 23:29:56 | BidiX | [[/|http://tiddlywiki.bidix.info/#%5B%5BExtension%20directory%5D%5D]] | [[store.php|http://TiddlyWiki.bidix.info/store.php]] | . | [[index.html | http://TiddlyWiki.bidix.info/index.html]] | backup |
UploadPlugin uses the following sequence for finding parameters :
#''macro'' parameters
#''Options'' saved in cookies
#''Plugin'' default values
!Options used by UploadPlugin
| Option | Value | Default |
|Upload Username: |<<option txtUploadUserName>>| |
|Upload Password: |<<option pasUploadPassword>>| |
|Url of the UploadService script: |<<option txtUploadStoreUrl urlInput>>| store.php |
|Relative Directory where to store the file: |<<option txtUploadDir urlInput>>| . (the script directory) |
|Filename of the uploaded file: |<<option txtUploadFilename urlInput>>| index.html |
|Directory to backup file on webserver^^(1)^^: |<<option txtUploadBackupDir urlInput>>| //null// (none/no backup) |
|Log in UploadLog |<<option chkUploadLog>> Trace Upload| true |
|Maximum of lines in UploadLog |<<option txtUploadLogMaxLine>>| 10 |
^^(1)^^No backup if Backup Directory is empty, the previous file will be overwritten. Use a '.' to backup in the script directory.
<<upload>> with these options.
!Upload Macro parameters
{{{
<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
Optional positional parameters can be passed to overwrite UploadOptions.
}}}
!UploadToFile Macro Macro parameters
{{{
<<uploadTofile [filename [tiddlerTitle]]>>
tiddlerTitle, filename: if omitted the title of the current tiddler
}}}
<<uploadToFile allowedsites.txt allowedsites.txt>>
I'm pleased to announce UploadPlugin 4.1.
!!It works as it did ...
First this new version is a ''refactored version''. That is to say that UploadPlugin works as it did before. But thanks to a number of enhancements in TiddlyWiki <<version>>, now it is based on the core HTTP functions for the low level AJAX and it does no more core hijacking. It also uses only core functions for the HTML and RSS file generation. So UploadPlugin will stay compatible with future evolution of StoreArea, ExtendedFields, FileTemplates ...
!!... but even better
In addition to the {{{<<upload>>}}} macro, an entry in Backstage is also provided. An experimental UploadToHomeMacro using HomeParameters shadowed tiddler is also released, for now, as a separate plugin.
A lot of small enhancements (better messages, debugMode ...) and better reliability.
And the good news are that UploadLog :
*is optional,
*is automatically truncated,
*stores only the last uploads.
This new release includes also new versions of : UploadOptions, UploadPluginDoc, UploadForm, UploadPluginLingoFR, UploadPluginLingoEN. All tagged <<tag Upload>>
UploadPlugin requires PasswordOptionPlugin in your TiddlyWiki and an UploadService on the WebServer to store the TiddlyWiki file. Even if UploadPlugin 4.1 is compatible with previous store scripts, the easiest script to set up is [[store.php]] version 1.6.0
Since TiddlyWiki 2.2 is in beta stage, you will find this release at http://tiddlylab.bidix.info/#Upload and also in the SVN repository at http://trac.tiddlywiki.org/tiddlywiki/browser/Trunk/contributors/BidiX
Comments and suggestions are welcome.
Enjoy,
-- BidiX
http://tiddlywiki.bidix.info
When TiddlyWiki location is {{{file}}}, UploadPlugin doesn't encode properly characters in RSS file.
This is fixed in this release.
Enjoy UploadPlugin !
-- BidiX
Paulo Soares reported some compatibility problems for UploadPlugin in IE 7 and Firefox 3 B3 : [[TiddlyWiki Google Group|http://groups.google.com/group/TiddlyWiki/browse_thread/thread/bdbb09bdfaf4e07d/911892dd1e1a402c]]. Thanks Paulo.
This new minor revision should solve this.
Enjoy UploadPlugin !
-- BidiX
----
UploadPlugin V 4.1.3 (2008/02/24)
*Small enhancement :
**new config.macros.uploadOptions.options for UploadOptions extensions
UploadPlugin V 4.1.2 (2008/02/23)
*Small corrections in :
**config.macros.uploadOptions macro for IE7 compatibilty
**bidix.upload.httpUpload function for FF 3 B3 compatibility
**bidix.upload.uploadChanges function for Safari on iPhone compatibility
UploadPlugin V 4.1.4 (2008-08-11) :
Using {{{404}}} instead of obsolete (in TW 2.4.1) {{{httpStatus.NotFound}}}.
Thanks Fred for figuring out and correcting the problem.
Enjoy UploadPlugin !
-- BidiX
Thanks to PacoRivière, UploadPlugin has its Catalan Translation: UploadPluginLingoCA
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.4|
|''Date:''|2008-08-11|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 4,
date: new Date("2008-08-11"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
//
// Upload Macro
//
config.macros.upload = {
// default values
defaultBackupDir: '', //no backup
defaultStoreScript: "store.php",
defaultToFilename: "index.html",
defaultUploadDir: ".",
authenticateUser: true // UploadService Authenticate User
};
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
config.macros.upload.handler = function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = this.label.saveLabel;
else
label = this.label.uploadLabel;
var prompt;
if (params[0]) {
prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
} else {
prompt = this.label.promptOption;
}
createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};
config.macros.upload.action = function(params)
{
// for missing macro parameter set value from options
if (!params) params = {};
var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
var username = params[4] ? params[4] : config.options.txtUploadUserName;
var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
// for still missing parameter set default value
if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
if (storeUrl.substr(0,4) != "http")
storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
if (!toFilename)
toFilename = bidix.basename(window.location.toString());
if (!toFilename)
toFilename = config.macros.upload.defaultToFilename;
if (!uploadDir)
uploadDir = config.macros.upload.defaultUploadDir;
if (!backupDir)
backupDir = config.macros.upload.defaultBackupDir;
// report error if still missing
if (!storeUrl) {
alert(config.macros.upload.messages.noStoreUrl);
clearMessage();
return false;
}
if (config.macros.upload.authenticateUser && (!username || !password)) {
alert(config.macros.upload.messages.usernameOrPasswordMissing);
clearMessage();
return false;
}
bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
return false;
};
config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
{
if (!storeUrl)
return null;
var dest = bidix.dirname(storeUrl);
if (uploadDir && uploadDir != '.')
dest = dest + '/' + uploadDir;
dest = dest + '/' + toFilename;
return dest;
};
//
// uploadOptions Macro
//
config.macros.uploadOptions = {
handler: function(place,macroName,params) {
var wizard = new Wizard();
wizard.createWizard(place,this.wizardTitle);
wizard.addStep(this.step1Title,this.step1Html);
var markList = wizard.getElement("markList");
var listWrapper = document.createElement("div");
markList.parentNode.insertBefore(listWrapper,markList);
wizard.setValue("listWrapper",listWrapper);
this.refreshOptions(listWrapper,false);
var uploadCaption;
if (document.location.toString().substr(0,4) == "http")
uploadCaption = config.macros.upload.label.saveLabel;
else
uploadCaption = config.macros.upload.label.uploadLabel;
wizard.setButtons([
{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
onClick: config.macros.upload.action},
{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
]);
},
options: [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine"
],
refreshOptions: function(listWrapper) {
var opts = [];
for(i=0; i<this.options.length; i++) {
var opt = {};
opts.push();
opt.option = "";
n = this.options[i];
opt.name = n;
opt.lowlight = !config.optionsDesc[n];
opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
opts.push(opt);
}
var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
for(n=0; n<opts.length; n++) {
var type = opts[n].name.substr(0,3);
var h = config.macros.option.types[type];
if (h && h.create) {
h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
}
}
},
onCancel: function(e)
{
backstage.switchTab(null);
return false;
},
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
};
//
// upload functions
//
if (!bidix.upload) bidix.upload = {};
if (!bidix.upload.messages) bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved",
backupFailed: "Failed to upload backup file",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
var callback = function(status,uploadParams,original,url,xhr) {
if (!status) {
displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
return;
}
if (bidix.debugMode)
alert(original.substr(0,500)+"\n...");
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.upload.uploadRss(uploadParams,original,posDiv);
};
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
// save on localdisk ?
if (document.location.toString().substr(0,4) == "file") {
var path = document.location.toString();
var localPath = getLocalPath(path);
saveChanges();
}
// get original
var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
var originalPath = document.location.toString();
// If url is a directory : add index.html
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + "index.html";
var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
var log = new bidix.UploadLog();
log.startUpload(storeUrl, dest, uploadDir, backupDir);
displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
if (bidix.debugMode)
alert("about to execute Http - GET on "+originalPath);
var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
bidix.upload.uploadRss = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
bidix.upload.uploadMain(params[0],params[1],params[2]);
} else {
displayMessage(bidix.upload.messages.rssFailed);
}
};
// do uploadRss
if(config.options.chkGenerateAnRssFeed) {
var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
var rssString = generateRss();
// no UnicodeToUTF8 conversion needed when location is "file" !!!
if (document.location.toString().substr(0,4) != "file")
rssString = convertUnicodeToUTF8(rssString);
bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
} else {
bidix.upload.uploadMain(uploadParams,original,posDiv);
}
};
bidix.upload.uploadMain = function(uploadParams,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
var log = new bidix.UploadLog();
if(status) {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
store.setDirty(false);
log.endUpload("ok");
} else {
alert(bidix.upload.messages.mainFailed);
displayMessage(bidix.upload.messages.mainFailed);
log.endUpload("failed");
}
};
// do uploadMain
var revised = bidix.upload.updateOriginal(original,posDiv);
bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};
bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
var localCallback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (xhr.status == 404)
alert(bidix.upload.messages.storePhpNotFound.format([url]));
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
if (responseText.charAt(0) != '0')
status = null;
callback(status,params,responseText,url,xhr);
};
// do httpUpload
var boundary = "---------------------------"+"AaB03x";
var uploadFormName = "UploadPlugin";
// compose headers data
var sheader = "";
sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
sheader += uploadFormName +"\"\r\n\r\n";
sheader += "backupDir="+uploadParams[3] +
";user=" + uploadParams[4] +
";password=" + uploadParams[5] +
";uploaddir=" + uploadParams[2];
if (bidix.debugMode)
sheader += ";debug=1";
sheader += ";;\r\n";
sheader += "\r\n" + "--" + boundary + "\r\n";
sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
sheader += "Content-Length: " + data.length + "\r\n\r\n";
// compose trailer data
var strailer = new String();
strailer = "\r\n--" + boundary + "--\r\n";
data = sheader + data + strailer;
if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
if (typeof r == "string")
displayMessage(r);
return r;
};
// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
if (!posDiv)
posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
store.allTiddlersAsHtml() + "\n" +
original.substr(posDiv[1]);
var newSiteTitle = getPageTitle().htmlEncode();
revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
return revised;
};
//
// UploadLog
//
// config.options.chkUploadLog :
// false : no logging
// true : logging
// config.options.txtUploadLogMaxLine :
// -1 : no limit
// 0 : no Log lines but UploadLog is still in place
// n : the last n lines are only kept
// NaN : no limit (-1)
bidix.UploadLog = function() {
if (!config.options.chkUploadLog)
return; // this.tiddler = null
this.tiddler = store.getTiddler("UploadLog");
if (!this.tiddler) {
this.tiddler = new Tiddler();
this.tiddler.title = "UploadLog";
this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
this.tiddler.created = new Date();
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
}
return this;
};
bidix.UploadLog.prototype.addText = function(text) {
if (!this.tiddler)
return;
// retrieve maxLine when we need it
var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
if (isNaN(maxLine))
maxLine = -1;
// add text
if (maxLine != 0)
this.tiddler.text = this.tiddler.text + text;
// Trunck to maxLine
if (maxLine >= 0) {
var textArray = this.tiddler.text.split('\n');
if (textArray.length > maxLine + 1)
textArray.splice(1,textArray.length-1-maxLine);
this.tiddler.text = textArray.join('\n');
}
// update tiddler fields
this.tiddler.modifier = config.options.txtUserName;
this.tiddler.modified = new Date();
store.addTiddler(this.tiddler);
// refresh and notifiy for immediate update
story.refreshTiddler(this.tiddler.title);
store.notify(this.tiddler.title, true);
};
bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
if (!this.tiddler)
return;
var now = new Date();
var text = "\n| ";
var filename = bidix.basename(document.location.toString());
if (!filename) filename = '/';
text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
text += config.options.txtUserName + " | ";
text += "[["+filename+"|"+location + "]] |";
text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
text += uploadDir + " | ";
text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
text += backupDir + " |";
this.addText(text);
};
bidix.UploadLog.prototype.endUpload = function(status) {
if (!this.tiddler)
return;
this.addText(" "+status+" |");
};
//
// Utilities
//
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
bidix.dirname = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
bidix.basename = function(filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("#")) != -1)
filePath = filePath.substring(0, lastpos);
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(lastpos + 1);
} else
return filePath.substring(filePath.lastIndexOf("\\")+1);
};
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);
// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
//}}}
//last update: UploadPlugin v 4.1.3//
!Description
UploadPlugin with <<tag UploadService>> extend TiddlyWiki with @@upload@@ and @@save to web@@ commands.
UploadPlugin uses Username and Password from UploadOptions stored in cookies to authenticate itself to [[store.php]] or [[store.cgi]].
UploadPlugin requires PasswordOptionPlugin.
French translation available as a separate tiddler UploadPluginMsgFR
!!UploadPlugin
*If the TiddlyWiki is viewed @@from local disk@@ :
**{{{<<upload ...>>}}}
***display as '''upload'''
***after saving to disk, upload to a website.
*If the TiddlyWiki is viewed @@from a website@@ :
**{{{<<upload ...>>}}}
***display as '''save to web'''
***save to the same website.
*If GenerateAnRssFeed in AdvancedOptions is set :
**generate the content of the RSSFeed
**upload the RssFile
**Caution : use the SiteUrl tiddler to specify the right url of the TiddlyWiki in the generated RssFile
*DisplayMessage
*If a backupDir is specified
**and if a file already exists in the uploadDir withe the same fielname, move it in the backup dir and rename it with a timestamp
*if UploadLog is activated every upload action is logged in UploadLog
**only the last maxLines are stored
**if maxLine = -1 no truncation will occured
hint : if UploadLog is the first tiddler in the TimelineTab, no tiddler has been changed since last upload.
!![[store.php]]
*UserVariables to set :
//{{{
$AUTHENTICATE_USER = true; // true | false
$USERS = array(
'UserName1'=>'Password1',
'UserName2'=>'Password2',
'UserName3'=>'Password3'); // set usernames and strong passwords
$DEBUG = false; // true | false
//}}}
*method GET
**display an information page
*method POST
**if $~AUTHENTICATE_USER is ''true''
***presence and value of user and password are checked with $USER and $PASSWORD
**if toFilename already exists and backDir parameter specified
***rename toFilename to backupDir/toFilename.AAAAMMDD.HHSS.html
**copy temporaryUploadedFile toFilename
**return status
!![[store.cgi]]
*UserVariables to set :
//{{{
CONFIG = {
:users => {
'UserName1'=>'Password1',
'UserName2'=>'Password2',
'UserName3'=>'Password3')
},
:authenticateUser => true,
:backupExistingFile => true,
:withUploadDir => true
}
//}}}
*same processing as store.php above
!Usage :
{{{
<<upload>>
uses UploadOptions saved in cookies :
txtUploadUserName: username
pasUploadPassword : password
txtUploadStoreUrl : store script
txtUploadDir : relative path for upload directory
txtUploadFilename : upload filename
txtUploadBackupDir : relative path for backup directory
<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
Optional positional parameters can be passed to overwrite
UploadOptions.
}}}
Suggestion: Install the {{{<<upload ... >>}}} macro in SideBarOptions just below {{{<<saveChanges>>}}} macro.
!User manual
See HowToUpload
!Installation :
*Install the UploadPlugin as usual
*[[Upload]] the [[store.php]] file on your php aware webserver in your TiddlyWiki directory
*Protect your server against malicious upload. Two approaches :
**set $~AUTHENTICATE_USER to true in the [[store.php]] script
***configure $USER and $PASSWORD in the [[store.php]] script on your webserver
***set UploadOptions in conformity with [[store.php]]
**Use server protection :
***for Apache web server ([[for detail see Apache documentation|http://httpd.apache.org/docs/1.3/howto/htaccess.html]]) :
****configure and upload the [[.htaccess]] [[.passwd]]
***for other web servers see the appropriate documentation
*Configure an upload button, for example in the SideBarOptions
!Suppported Browser
*Firefox and Gecko based browser: tested Ok
*Internet Explorer : tested Ok
*Safari : tested ok on OS X
*Others : Not tested, please report status.
!Revision history
<<tiddler UploadPluginRevisionHistory>>
/***
|''Name:''|UploadPluginLingoCA|
|''Description:''|Catalan Translation|
|''Version:''|4.1.0|
|''Date:''|July 15, 2007|
|''Source:''|http://pacoriviere.googlepages.com/UploadPluginLingoCA.js|
|''Author:''|PacoRivière (web (at) pacoriviere (dot) cat)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
|''Requires:''|UploadPlugin UploadToHomeMacro|
***/
//{{{
config.macros.upload.label = {
promptOption: "Desa aquest TiddlyWiki i puja'l amb UploadOptions",
promptParamMacro: "Desa aquest TiddlyWiki i puja'l a %0",
saveLabel: "desa a la web",
saveToDisk: "desa al disc",
uploadLabel: "puja"
};
config.macros.upload.messages = {
noStoreUrl: "No s'ha desat la URL als paràmetres o opcions",
usernameOrPasswordMissing: "Falta el nom d'usuari o contrassenya"
};
merge(config.macros.uploadOptions, {
wizardTitle: "Puja amb opcions",
step1Title: "Aquestes opcions es desen en galetes del vostre navegador",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Anul·la",
cancelButtonPrompt: "Avís d'anul·lació",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Descripció", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Opció", type: 'String'},
{name: 'Name', field: 'name', title: "Nom", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
bidix.upload.messages = {
//from saving
invalidFileError: "Sembla que l'arxiu original '%0' no és un TiddlyWiki vàlid",
backupSaved: "S'ha desat la còpia de seguretat a la web",
backupFailed: "No ha estat possible desar la còpia de seguretat a la web",
rssSaved: "S'ha pujat el canal RSS",
rssFailed: "No ha estat possible pujar l'arxiu del canal RSS",
emptySaved: "S'ha pujat la plantilla buida",
emptyFailed: "No ha estat possible pujar l'arxiu de plantilla buit",
mainSaved: "S'ha pujat l'arxiu principal de TiddlyWiki",
mainFailed: "No ha estat possible pujar l'arxiu principal de TiddlyWiki. No s'han desat els vostres canvis",
//specific upload
loadOriginalHttpPostError: "No es pot obtenir l'arxiu original",
aboutToSaveOnHttpPost: 'Quant a pujar a %0 ...',
storePhpNotFound: "No s'ha trobat la seqüència per pujar '%0'."
};
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url de la seqüència del servei de pujada, UploadService (per omissió: store.php)",
txtUploadFilename: "Nom de l'arxiu a pujar (per omissió: a index.html)",
txtUploadDir: "Carpeta Relativa per desar l'arxiu (per omissió: . (downloadService directory))",
txtUploadBackupDir: "Carpeta Relativa per desar la còpia de seguretat. Si és buit no es fa la còpia. (per omissió: ''(buit))",
txtUploadUserName: "Nom d'usuari per pujar",
pasUploadPassword: "Contrassenya per pujar",
chkUploadLog: "Porta un registre a UploadLog (per omissió: cert)",
txtUploadLogMaxLine: "Nombre màxim de línies del registre de pujada, UploadLog (per omissió: 10)"
});
merge(config.tasks,{
uploadOptions: {text: "puja", tooltip: "Canvia les UploadOptions i puja", content: '<<uploadOptions>>'}
});
//}}}
//{{{
/*
* UploadToHomeMacro Lingo
*/
if (config.macros.uploadToHome) {
merge(config.macros.uploadToHome,{messages: {
homeParamsTiddler: "HomeParameters",
prompt: "Desa aquest TiddlyWiki i puja'l amb els paràmeters del tiddler '%0'",
tiddlerNotFound: "No s'ha trobat el Tiddler %0"
}});
merge(config.tasks,{
uploadToHome: {text: "uploadToHome", tooltip: "Puja amb '" + config.macros.uploadToHome.messages.homeParamsTiddler + "' tiddler",
action: config.macros.uploadToHome.action}
});
}
//}}}
/***
|''Name:''|UploadPluginLingoEN|
|''Description:''|English Translation|
|''Version:''|4.1.0|
|''Date:''|May 8, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPluginLingoEN|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
|''Requires:''|UploadPlugin UploadToHomeMacro|
***/
//{{{
config.macros.upload.label = {
promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
promptParamMacro: "Save and Upload this TiddlyWiki in %0",
saveLabel: "save to web",
saveToDisk: "save to disk",
uploadLabel: "upload"
};
config.macros.upload.messages = {
noStoreUrl: "No store URL in parmeters or options",
usernameOrPasswordMissing: "Username or password missing"
};
merge(config.macros.uploadOptions, {
wizardTitle: "Upload with options",
step1Title: "These options are saved in cookies in your browser",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Cancel",
cancelButtonPrompt: "Cancel prompt",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Name', field: 'name', title: "Name", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
bidix.upload.messages = {
//from saving
invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
backupSaved: "Backup saved on web",
backupFailed: "Failed to save backup file on web",
rssSaved: "RSS feed uploaded",
rssFailed: "Failed to upload RSS feed file",
emptySaved: "Empty template uploaded",
emptyFailed: "Failed to upload empty template file",
mainSaved: "Main TiddlyWiki file uploaded",
mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
//specific upload
loadOriginalHttpPostError: "Can't get original file",
aboutToSaveOnHttpPost: 'About to upload on %0 ...',
storePhpNotFound: "The store script '%0' was not found."
};
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
txtUploadUserName: "Upload Username",
pasUploadPassword: "Upload Password",
chkUploadLog: "do Logging in UploadLog (default: true)",
txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
//}}}
//{{{
/*
* UploadToHomeMacro Lingo
*/
if (config.macros.uploadToHome) {
merge(config.macros.uploadToHome,{messages: {
homeParamsTiddler: "HomeParameters",
prompt: "Save and Upload this TiddlyWiki using parameters in '%0' tiddler",
tiddlerNotFound: "Tiddler %0 not found"
}});
merge(config.tasks,{
uploadToHome: {text: "uploadToHome", tooltip: "Upload using '" + config.macros.uploadToHome.messages.homeParamsTiddler + "' tiddler",
action: config.macros.uploadToHome.action}
});
}
//}}}
/***
|''Name:''|UploadPluginLingoFR|
|''Description:''|French Translation|
|''Version:''|4.1.0|
|''Date:''|May 8, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPluginLingoFR|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|UploadPlugin UploadToHomeMacro|
***/
//{{{
config.macros.upload.label = {
promptOption: "Sauvegarde et télécharge ce TiddlyWiki avec les UploadOptions",
promptParamMacro: "Sauvegarde et télécharge ce TiddlyWiki vers %0",
saveLabel: "sauvegarde sur le web",
saveToDisk: "sauvegarde sur le disque",
uploadLabel: "Télécharge vers le web"
};
config.macros.upload.messages = {
noStoreUrl: "Pas de 'store URL' dans les paramètres ou dans les options",
usernameOrPasswordMissing: "nom d'utilisateur ou mot de passe absent"
};
merge(config.macros.uploadOptions, {
wizardTitle: "Télécharge avec les options",
step1Title: "Ces options sont sauvegardées dans des cookies de votre navigateur",
step1Html: "<input type='hidden' name='markList'></input><br>",
cancelButton: "Annuler",
cancelButtonPrompt: "Arrête l'action en cours et ferme le panneau",
listViewTemplate: {
columns: [
{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
{name: 'Option', field: 'option', title: "Option", type: 'String'},
{name: 'Nom', field: 'name', title: "Nom", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
bidix.upload.messages = {
//from saving
invalidFileError: "Le fichier '%0' d'origine ne semble pas être un TiddlyWiki valide",
backupSaved: "backup enegistré sur le web",
backupFailed: "Echec de l'enregistrement du backup sur le web",
rssSaved: "Flux RSS a été téléchargé",
rssFailed: "Echec du téléchargement du flux RSS",
emptySaved: "Fichier de base 'empty.html' téléchargé",
emptyFailed: "Echec du téléchargement du fichier de base 'empty.html'",
mainSaved: "Fichier principal TiddlyWiki téléchargé",
mainFailed: "Echec du téléchargement du fichier principal TiddlyWiki. Vos modifications n'ont pas été téléchargées",
//specific upload
loadOriginalHttpPostError: "Le fichier d'origine n'a pas pu être accédé",
aboutToSaveOnHttpPost: "Préparation du téléchargement du TiddlyWiki vers %0 ...",
storePhpNotFound: "Le script de téléchargement '%0' n'a pas pu être trouvé."
};
merge(config.optionsDesc,{
txtUploadStoreUrl: "Url du script du Service de Téléchargement (defaut : store.php)",
txtUploadFilename: "Nom du fichier à télécharger vers le web (defaut : in index.html)",
txtUploadDir: "Repertoire relatif où télécharger le fichier (defaut : . (répertoire du Service de Téléchargement))",
txtUploadBackupDir: "Repertoire relatif où sauvegarder le fichier précédent. Si vide il n'y aura pas de sauvegarde. (defaut : '' (néant))",
txtUploadUserName: "Nom d'utilisateur pour le Téléchargement",
pasUploadPassword: "Mot de passe pour le Téléchargement",
chkUploadLog: "Enregistre une trace dans UploadLog (defaut: true)",
txtUploadLogMaxLine: "Nomnre maximum de lignes dans UploadLog (defaut: 10)"
});
merge(config.tasks,{
uploadOptions: {text: "télécharge", tooltip: "Edite les options et télécharge vers le seveur", content: '<<uploadOptions>>'}
});
//}}}
//{{{
/*
* UploadToHomeMacro Lingo
*/
if (config.macros.uploadToHome) {
merge(config.macros.uploadToHome,{messages: {
homeParamsTiddler: "HomeParameters",
prompt: "Sauvegarde et télécharge ce TiddlyWiki en utilisant les paramètres du tiddler '%0'",
tiddlerNotFound: "Tiddler %0 non trouvé"
}});
merge(config.tasks,{
uploadToHome: {text: "téléchargeVersMaison", tooltip: "Télécharge en utilisant le tiddler '" + config.macros.uploadToHome.messages.homeParamsTiddler + "'", action: config.macros.uploadToHome.action}
});
}
//}}}
* V 4.1.4 (2008-08-11) :
** Using {{{404}}} instead of obsolete (in TW 2.4.1) {{{httpStatus.NotFound}}}. Thanks Fred for figuring out and correcting the problem.
*V 4.1.3 (2008/02/24)
**Small enhancement :
***new config.macros.uploadOptions.options for UploadOptions extensions
*V 4.1.2 (2008/02/23)
**Small corrections in :
***config.macros.uploadOptions macro for IE7 compatibilty
***bidix.upload.httpUpload function for FF 3 B3 compatibility
***bidix.upload.uploadChanges function for Safari on iPhone compatibility
*V 4.1.1 (2007/09/15)
**In UploadRss, no UnicodeToUTF8 conversion needed when location is "file"
*V 4.1.0 (2007/05/05)
**uploadOptions macro
**Backstage entry added
**Sync with #2135 TiddlyWiki core
***MarkupPostBody change
***getPageTitle()
*V 4.0.2 (2007/04/21)
**Compatibilty with TW 2.2 beta5
*V 4.0.0 Beta 0 (2007/02/28)
**Code refactoring for using the core HTTP and Options functions
**PasswordOptionPlugin required
**UploadLog is optional and stores only a maxLine number of lines (see UploadOptions)
**the bidix.debugMode variable set to true activates debug both in UploadPlugin and in UploadService
**Enhancements and better reliability
**GroupAuthoring is pull out of UploadPlugin
**No more saveChanges hijacking
----
*V 3.4.5 (2006/10/15)
**Force checkAutoSave to false for http protocol only (thanks to SimonBaird)
*V 3.4.4 (2006/09/30)
**PasswordTweak V 1.0.3
***add class attribute specific on each option input (thanks to ClintChecketts)
**UploadOptions width set by styleSheet
*V 3.4.3 (2006/09/19)
**Add classname to input for options (thanks to ClintChecketts)
**Force checkAutoSave to false
**Alert if password is empty before Uploading
*V 3.4.2 (2006/09/04)
**add functions to format displayMessages (thanks to LucDeschenaux)
**take return values from store.cgi of destfile and backupfile for displayMessages
*V 3.4.1 (2006/08/19)
**Error management improvement
*V 3.4.0 (2006/07/25)
**Manage Lock parameters for GroupAuthoring
**Small code refactoring for new PluginFormat in TW 2.1
*V 3.3.3 (2006/06/30)
**reinstall saveChanges Hijacking
*V 3.3.2 (2006/06/26)
** make "save to disk" disappear when TiddlyWiki is located on the web
** small reformatting of post headers for store.cgi compatibility
*V 3.3.1 (2006/03/30)
**bug in backup folder when uploading rssfile fixed
*V 3.3.0 (2006/03/12)
**Code refactoring
**suppress saveChanges hijacking
*V3.2.2 (2006/02/25)
**Use PasswordTweak 1.0.1
**uploaddir is a relative path
**backupdir is a relative path
*V3.2.1 (2006/02/13)
**name and password added to open.request (Thanks to TedPavlic)
*V3.2.0 (2006/02/14)
**Use PassworDTweak (http://tiddlyWiki.bidix.info/#PasswordTweak) for password
*V3.1.0 (2006/02/12)
**UploadOptions in Cookies
**Username and password from UploadOptions pass to [[store.php]] script for authentification check
*V3.0.3 (2006/02/03)
**Firefox 1.5.0.1 crashes due to global var fixed
*V3.0.2 (2006/01/25/)
**HTTPS compatible
*V3.0.1 (2006/01/18)
**UTF8toUnicode conversion problem in Firefox
*V3.0.0 (2006/01/15)
**Asynchronous upload
**Synchronous upload before unload of the page
**All strings extracted in macro config
**Compatibility checked with TW 2.0.2 & TW 1.2.39 for both FF 1.5 and IE 6
*V2.0.2 (2006/01/08)
**conversion of SiteTitle and SiteSubtitle in web page Title
*V2.0.1 (2006/01/08)
**Compatibilty with TiddlyWiki 2.0.1
*V2.0.0 (2006/01/03)
**Save to web
**Compatibilty with TiddlyWiki 1.2.39 and TiddlyWiki 2.0.0 Beta 6
*v1.1.0 (2005/12/27)
**[[Upload]] RSS File
*v1.0.3 (2005/12/26)
**UploadLog tiddler
*v1.0.2 (2005/12/24)
**Optional parameter toFilename
**Optional parameter backupDir
*v1.0.1 (2005/12/23)
**reformatting code
* v1.0.0 (2005/12/17)
** first public working version
UploadTiddlerPlugin and [[storeTiddler.php]] "upload" or "save to web" a single tiddler by updating, inserting or deleting a single tiddler in a TiddlyWiki file located on the web.
@@Now UploadTiddlerPlugin is able to Upload a Tiddler even if TiddlyWiki is located on a local file.@@
![[UploadTiddlerPlugin]]
*is activated by @@chkUploadTiddler option: <<option chkUploadTiddler>>@@
* to be abe to Upload a Tiddler even if the TiddlyWiki is located on local file@@chkUploadTiddlerFromFile option: <<option chkUploadTiddlerFromFile>>@@
*uses @@txtUploadTiddlerStoreUrl: <<option txtUploadTiddlerStoreUrl>>@@
*override TiddlyWiki.prototype.saveTiddler and deleteTiddler core functions
*uses the same options as UploadPlugin.
*do an XmlHttpRequest POST to storeTiddler.php only with the corresponding tiddler in storeArea format.
![[storeTiddler.php]]
*Username and password are checked
*[[storeTiddler.php]] parses TiddlyWiki file
*tiddler is updated, inserted or deleted in the tiddler array
*optionally create and clean backup file
*write updated TiddlyWiki file
!UploadTiddlerPlugin and UploadPlugin
*The paradigm of UploadTiddlerPlugin and [[storeTiddler.php]] is exactly the same as UploadPlugin and [[store.php]]
*No concurrency managed
*Full compatible with UploadPlugin
*[[storeTiddler.php]] can be use to remotly update a TiddlyWiki. storeTiddler.php
*a GET to [[storeTiddler.php]] display a form to upload a tiddler in a TiddlyWiki
/***
|''Name:''|UploadTiddlerMacro|
|''Description:''|Define a macro to upload a tiddler using UploadTiddlerPlugin (see UploadTiddlerPlugin for details).|
|''Version:''|1.0.0|
|''Date:''|2008-09-30|
|''Source:''|http://tiddlywiki.bidix.info/#UploadTiddlerMacro|
|''Usage:''|{{{<<uploadTiddler [tiddlerTitle]>>}}}<br>{{{tiddlerTitle: if omitted the title of the current tiddler}}}|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
|''Requires:''|UploadTiddlerPlugin|
***/
//{{{
version.extensions.UploadTiddlerMacro = {
major: 1, minor: 0, revision: 0,
date: new Date("2008-09-30"),
source: 'http://tiddlywiki.bidix.info/#UploadTiddlerMacro',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
config.macros.uploadTiddler = {
label: "uploadTiddler",
prompt: "upload tiddler '%0' using UploadTiddlerOptions ",
warning: "Are you sure you want to upload '%0'?",
messages: {
fileUploaded: "tiddler '%0' uploaded to file '%1'",
fileNotUploaded: "tiddler '%0' NOT uploaded"
},
handler: function(place, macroName, params, wikifier,paramString, tiddler) {
var tiddlerTitle = params[0];
if (!tiddlerTitle) {
tiddlerTitle = tiddler.title;
} else {
tiddler = store.getTiddler(tiddlerTitle);
}
createTiddlyButton(place, this.label, this.prompt.format([tiddlerTitle]),
function () {
config.macros.uploadTiddler.upload(tiddlerTitle, tiddler);
return false;},
null, null, null);
},
upload: function(tiddlerTitle, tiddler) {
var saved_chkUploadTiddler = config.options.chkUploadTiddler;
config.options.chkUploadTiddler = true;
bidix.uploadTiddler.upload(tiddlerTitle, tiddler,tiddlerTitle);
config.options.chkUploadTiddler = saved_chkUploadTiddler;
}
};
//
// Utilities
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
//
// Initializations
//
// require UploadTiddlerPlugin 1.2.2 or better
bidix.checkPlugin("UploadTiddlerPlugin", 1, 2, 2);
//}}}
/***
|''Name:''|UploadTiddlerPlugin|
|''Description:''|Upload a tiddler and Update a remote TiddlyWiki |
|''Version:''|1.2.2|
|''Date:''|2008-09-13|
|''Source:''|http://tiddlywiki.bidix.info/#UploadTiddlerPlugin|
|''Usage:''|Uses {{{<<uploadOptions>>}}}<br>with those UploadTiddler Options : <br>chkUploadTiddler: <<option chkUploadTiddler>><br>txtUploadTiddlerStoreUrl: <<option txtUploadTiddlerStoreUrl>><br>chkUploadTiddlerFromFile: <<option chkUploadTiddlerFromFile>>|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''[[License]]:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.3.0|
***/
//{{{
version.extensions.UploadTiddlerPlugin = {
major: 1, minor: 2, revision: 2,
date: new Date("2008-09-13"),
source: 'http://tiddlywiki.bidix.info/#UploadTiddlerPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.3.0'
};
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;
bidix.uploadTiddler = {
messages: {
aboutToSaveTiddler: "About to update tiddler '%0'...",
aboutToRemotelySaveTiddler: "About to REMOTELY update tiddler '%0'...",
storeTiddlerNotFound: "Script store tiddler '%0' not found",
tiddlerSaved: "Tiddler '%0' updated in '%1' using '%2' "
},
upload: function(title,tiddler,oldTitle) {
var callback = function(status,params,responseText,url,xhr) {
if (xhr.status == 404) {
alert(bidix.uploadTiddler.messages.storeTiddlerNotFound.format([url]));
return;
}
if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
alert(responseText);
if (responseText.indexOf("Debug mode") >= 0 )
responseText = responseText.substring(responseText.indexOf("\n\n")+2);
} else if (responseText.charAt(0) != '0')
alert(responseText);
else
displayMessage(bidix.uploadTiddler.messages.tiddlerSaved.format([params[0], params[1], params[2]]));
store.setDirty(false);
}
if ((config.options['chkUploadTiddler']) &&
((document.location.toString().substr(0,4) == "http") || config.options['chkUploadTiddlerFromFile'])) {
clearMessage();
if (document.location.toString().substr(0,4) != "http")
displayMessage(bidix.uploadTiddler.messages.aboutToRemotelySaveTiddler.format([title]));
else
displayMessage(bidix.uploadTiddler.messages.aboutToSaveTiddler.format([title]));
var ExtTiddler = null;
var html = null;
if (tiddler) {
ExtTiddler = store.getSaver().externalizeTiddler(store,tiddler);
html = wikifyStatic(tiddler.text,null,tiddler).htmlEncode();
}
var form = "title="+encodeURIComponent(title);
form = form + "&tiddler="+(ExtTiddler?encodeURIComponent(ExtTiddler):'');
form = form + "&html="+(html?encodeURIComponent(html):'');
var filename = (config.options['txtUploadFilename']?config.options['txtUploadFilename']:'index.html');
form = form +"&oldTitle="+encodeURIComponent(oldTitle);
form = form +"&fileName="+encodeURIComponent(filename);
form = form +"&backupDir="+encodeURIComponent(config.options['txtUploadBackupDir']);
form = form +"&user="+encodeURIComponent(config.options['txtUploadUserName']);
form = form +"&password="+encodeURIComponent(config.options['pasUploadPassword']);
form = form +"&uploadir="+encodeURIComponent(config.options['txtUploadDir']);
form = form +"&debug="+encodeURIComponent(0);
var storeScript = (config.options.txtUploadTiddlerStoreUrl
? config.options.txtUploadTiddlerStoreUrl : 'storeTiddler.php');
var r = doHttp("POST",storeScript,form+"\n",'application/x-www-form-urlencoded',
config.options['txtUploadUserName'],config.options['pasUploadPassword'],callback,Array(title,filename, storeScript),null);
}
}
}
TiddlyWiki.prototype.saveTiddler_bidix = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(oldTitle,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
var tiddler = TiddlyWiki.prototype.saveTiddler_bidix.apply(this,arguments);
var title = (newTitle?newTitle:oldTitle);
if (oldTitle == title)
oldTitle = '';
bidix.uploadTiddler.upload(title, tiddler, oldTitle);
}
TiddlyWiki.prototype.removeTiddler_bidix =TiddlyWiki.prototype.removeTiddler;
TiddlyWiki.prototype.removeTiddler = function(title) {
TiddlyWiki.prototype.removeTiddler_bidix.apply(this,arguments);
bidix.uploadTiddler.upload(title, null);
}
//
// Initializations
//
bidix.initOption = function(name,value) {
if (!config.options[name])
config.options[name] = value;
};
// styleSheet
setStylesheet('.txtUploadTiddlerStoreUrl {width: 22em;}',"uploadTiddlerPluginStyles");
//optionsDesc
merge(config.optionsDesc,{
txtUploadTiddlerStoreUrl: "Url of the UploadTiddlerService script (default: storeTiddler.php)",
chkUploadTiddler: "Do per Tiddler upload using txtUploadTiddlerStoreUrl (default: false)",
chkUploadTiddlerFromFile: "Upload tiddler even if TiddlyWiki is located on local file (default: false)"
});
// Options Initializations
bidix.initOption('txtUploadTiddlerStoreUrl','');
bidix.initOption('chkUploadTiddler','');
bidix.initOption('chkUploadTiddlerFromFile','');
// add options in backstage UploadOptions
if (config.macros.uploadOptions) {
if (config.macros.uploadOptions.options) {
config.macros.uploadOptions.options.push("txtUploadTiddlerStoreUrl","chkUploadTiddler", "chkUploadTiddlerFromFile");
}
}
//}}}
/***
|''Name:''|UploadToFileMacro|
|''Description:''|Upload a tiddler as a file using UploadPlugin context. Used with the SimonBaird's HideWhenPlugin ViewTemplate provides a new command in the tiddler toolbar.|
|''Version:''|2.0.1|
|''Date:''|Apr 21, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadToFileMacro|
|''Usage:''|{{{<<uploadTofile [filename [tiddlerTitle]]>>}}}<br>{{{tiddlerTitle, filename: if omitted the title of the current tiddler}}}|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''CoreVersion:''|2.2.0|
|''Requires:''|UploadPlugin|
***/
//{{{
version.extensions.UploadToFileMacro = {
major: 2, minor: 0, revision: 1,
date: new Date("Apr 21, 2007"),
source: 'http://tiddlywiki.bidix.info/#UploadToFilePlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0'
};
// require UploadPlugin 4.0.0 or better
config.macros.uploadToFile = {
label: "upload %0 to file %1",
prompt: "upload tiddler '%0' to file '%1' ",
warning: "Are you sure you want to upload '%0'?",
messages: {
fileUploaded: "tiddler '%0' uploaded to file '%1'",
fileNotUploaded: "tiddler '%0' NOT uploaded"
},
handler: function(place, macroName, params, wikifier,paramString, tiddler) {
// parameters initialization
var toFilename = params[0];
var tiddlerTitle = params[1];
if (!tiddlerTitle) {
tiddlerTitle = tiddler.title;
} else {
tiddler = store.getTiddler(tiddlerTitle);
}
if (!toFilename) {
toFilename = tiddlerTitle;
}
var prompt = this.prompt.format([tiddlerTitle, toFilename]);
createTiddlyButton(place, this.label.format([params[1], params[0]]), this.prompt.format([tiddlerTitle, toFilename]),
function () {
config.macros.uploadToFile.upload(tiddler, null, toFilename);
return false;},
null, null, null);
},
upload: function(tiddler, storeUrl, toFilename, uploadDir, backupDir, username, password) {
if (!tiddler) {
alert("Tiddler not found.");
return false;
}
var uploadIt = true;
if ((this.warning) && (!confirm(this.warning.format([tiddler.title]))))
return false;
// parameters initialization
storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);
toFilename = (toFilename ? toFilename : tiddler.title);
backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);
uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);
username = (username ? username : config.options.txtUploadUserName);
password = (password ? password :config.options.pasUploadPassword);
var callback = function(status,params,responseText,url,xhr) {
if (status) {
if (responseText.substring(0,1) == '0') {
// if backupDir specified
if ((params[3]) && (responseText.indexOf("backupfile:") > -1)) {
var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,
responseText.indexOf("\n", responseText.indexOf("backupfile:")));
displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
}
var destfile = responseText.substring(responseText.indexOf("destfile:")+9,
responseText.indexOf("\n", responseText.indexOf("destfile:")));
if (destfile.substring(0,2) == './')
destfile = destfile.substring(2);
displayMessage(config.macros.uploadToFile.messages.fileUploaded.format([params[6],destfile]),
bidix.dirname(url)+'/'+destfile);
} else {
alert(responseText);
displayMessage(config.macros.uploadToFile.messages.fileNotUploaded.format([params[1]]));
}
} else {
displayMessage("HTTP Error " + xhr.status + " in accessing " + url);
}
};
var uploadParams = Array(storeUrl,toFilename,uploadDir,backupDir,username,password, tiddler.title);
return bidix.upload.httpUpload(uploadParams,tiddler.text,callback,uploadParams);
}
};
bidix.checkPlugin = function(plugin, major, minor, revision) {
var ext = version.extensions[plugin];
if (!
(ext &&
((ext.major > major) ||
((ext.major == major) && (ext.minor > minor)) ||
((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
// write error in PluginManager
if (pluginInfo)
pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
}
};
//
// Initializations
//
// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("UploadPlugin", 4, 0, 0);
//}}}
/***
|''Name:''|UploadToHomeMacro|
|''Description:''|Save TiddlyWiki using HomeParameters tiddler|
|''Version:''|0.0.2|
|''Date:''|May 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#UploadToHomeMacro|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (#2125)|
|''Requires:''|UploadPlugin|
|''Usage:''|{{{<<uploadToHome [HomeParameters]>>}}}<br>{{{HomeParameters:}}} optional - Tiddler with upload parameters in slices (see HomeParameters).|
***/
//{{{
version.extensions.UploadToHomeMacro = {
major: 0, minor: 0, revision: 2,
date: new Date("May 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#UploadToHomeMacro',
author: 'BidiX (BidiX (at) bidix (dot) info',
coreVersion: '2.2.0 (#3125)'
};
//
// Environment
//
if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false; // true to activate both in Plugin and UploadService
bidix.checkPlugin("UploadPlugin", 4, 1, 0);
//
// uploadUsing Macro
//
config.macros.uploadToHome = {
handler: function(place,macroName,params) {
if (readOnly)
return;
var label;
if (document.location.toString().substr(0,4) == "http")
label = config.macros.upload.label.saveLabel;
else
label = config.macros.upload.label.uploadLabel;
var prompt;
var homeParams = (params[0] ? params[0]:this.messages.homeParamsTiddler);
if (store.tiddlerExists(homeParams) || store.isShadowTiddler(homeParams)) {
prompt = this.messages.prompt.toString().format([homeParams]);
} else {
throw(this.messages.tiddlerNotFound.toString().format([homeParams]));
}
var prompt = this.messages.prompt.toString().format([homeParams]);
createTiddlyButton(place, label, prompt, function() {config.macros.uploadToHome.action(homeParams);}, null, null, this.accessKey);
},
action: function(homeParams) {
homeParams = (homeParams ? homeParams : config.macros.uploadToHome.messages.homeParamsTiddler);
if (!store.tiddlerExists(homeParams) && !store.isShadowTiddler(homeParams)) {
throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([homeParams]));
}
config.macros.upload.action(config.macros.uploadToHome.getParamsFromTiddler(homeParams));
},
getParamsFromTiddler: function(tiddlerTitle) {
tiddlerTitle = (tiddlerTitle ? tiddlerTitle:this.messages.homeParamsTiddler);
if (!store.tiddlerExists(tiddlerTitle) && !store.isShadowTiddler(tiddlerTitle)) {
throw(config.macros.uploadToHome.messages.tiddlerNotFound.toString().format([tiddlerTitle]));
}
var sliceNames = [
"UploadStoreUrl",
"UploadFilename",
"UploadBackupDir",
"UploadDir",
"UploadUserName"
//"UploadPassword", // no password in tiddlers
];
var sliceValues = store.getTiddlerSlices(tiddlerTitle,sliceNames);
var parameters = [];
for(var i=0; i<sliceNames.length; i++) {
parameters.push(sliceValues[sliceNames[i]]);
}
return parameters;
},
messages: {
homeParamsTiddler: "HomeParameters",
prompt: "Save and Upload this TiddlyWiki using parameters in '%0' tiddler",
tiddlerNotFound: "Tiddler %0 not found"
},
initAtLoad: function () {
// install Shadowed HomeParameters
var storeUrl;
if ((document.location.toString().substr(0,4) == "http"))
storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
else
storeUrl = config.macros.upload.defaultStoreScript;
var shadowedHomeParameters = (config.shadowTiddlers['HomeParameters']?config.shadowTiddlers['HomeParameters']:'');
shadowedHomeParameters += [
"|UploadUserName:|"+config.options['txtUploadUserName']+"|",
"|UploadStoreUrl:|"+storeUrl+"|",
"|UploadDir:|.|",
"|UploadFilename:|index.html|",
"|UploadBackupDir:||"
].join("\n");
merge(config.shadowTiddlers,{'HomeParameters': shadowedHomeParameters});
// install Backstage uploadToHome
merge(config.tasks,{
uploadToHome: {text: "uploadToHome", tooltip: "Upload using '" + this.messages.homeParamsTiddler + "' tiddler", action: this.action}
});
config.backstageTasks.push("uploadToHome");
}
};
config.macros.uploadToHome.initAtLoad();
//}}}
WebDAVSavingPlugin permits to a TiddlyWiki accessed over HTTP to use the WebDAV protocol. It works exactly in the same way that saveChanges does, but on a website provided that it is WebDAV enabled.
This "save to webDAV" doesn't require any kind of ServerSide component and uses the standard TiddlyWiki Options :
><<option chkSaveBackups>> SaveBackups
><<option chkAutoSave>> AutoSave
><<option chkGenerateAnRssFeed>> GenerateAnRssFeed
><<option chkSaveEmptyTemplate>> SaveEmptyTemplate
>Folder name for backup files: <<option txtBackupFolder>>
The main functionalities are :
*save backup
*save RSS
*save an empty.html
*save main file
The plugin also checks for WebDAV capability of the webserver and creates remote folders if needed by the backup folder option (specified as a relative path).
You will find it at http://tiddlywiki.bidix.info/#WebDAVSavingPlugin and also in the svn repository at http://trac.tiddlywiki.org/browser/Trunk/contributors/BidiX/plugins/WebDAVSavingPlugin.js
For now, this plugin is in Version 0.2.1 and needs some enhancements to make it more easy to use and more reliable.
/***
|''Name:''|WebDAVSavingPlugin|
|''Description:''|Saves on a WebDAV server without the need of any ServerSide script.<br>When TiddlyWiki is accessed over http, this plugin permits to save back to the server, using http PUT.|
|''Version:''|0.2.1|
|''Date:''|Apr 21, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#WebDAVSavingPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.WebDAVSavingPlugin = {
major: 0, minor: 2, revision: 1,
date: new Date("Apr 21, 2007"),
source: 'http://tiddlywiki.bidix.info/#WebDAVSavingPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
if (!window.bidix) window.bidix = {};
bidix.WebDAVSaving = {
orig_saveChanges: saveChanges,
defaultFilename: 'index.html',
messages: {
loadOriginalHttpDavError: "Original file can't be loaded",
optionsMethodError: "The OPTIONS method can't be used on this ressource : %0",
webDavNotEnabled: "WebDAV is not enabled on this ressource : %0",
notHTTPUrlError: "WebDAV saving can be used for http viewed TiddlyWiki only",
aboutToSaveOnHttpDav: 'About to save on %0 ...' ,
folderCreated: "Remote folder '%0' created"
}
};
// Save this tiddlywiki with the pending changes
saveChanges = function(onlyIfDirty,tiddlers)
{
var originalPath = document.location.toString();
if (originalPath.substr(0,5) == "file:")
return bidix.WebDAVSaving.orig_saveChanges(onlyIfDirty,tiddlers);
else
return bidix.WebDAVSaving.saveChanges(onlyIfDirty,tiddlers);
}
bidix.WebDAVSaving.saveChanges = function(onlyIfDirty,tiddlers)
{
var callback = function(status,params,original,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (!status)
displayMessage(bidix.WebDAVSaving.messages.optionsMethodError.format([url]));
else {
if (!xhr.getResponseHeader("DAV"))
alert(bidix.WebDAVSaving.messages.webDavNotEnabled.format([url]));
else
bidix.WebDAVSaving.doSaveChanges();
}
}
if(onlyIfDirty && !store.isDirty())
return;
clearMessage();
var originalPath = document.location.toString();
// Check we were loaded from a HTTP or HTTPS URL
if(originalPath.substr(0,4) != "http") {
alert(bidix.WebDAVSaving.messages.notHTTPUrlError);
return;
}
// is the server WebDAV enabled ?
var r = doHttp("OPTIONS",originalPath,null,null,null,null,callback,null,null);
if (typeof r == "string")
alert(r);
}
bidix.WebDAVSaving.doSaveChanges = function()
{
var callback = function(status,params,original,url,xhr) {
if (!status) {
alert(config.messages.loadOriginalHttpDavError);
return;
}
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
// Locate the storeArea div's
var posDiv = locateStoreArea(original);
if((posDiv[0] == -1) || (posDiv[1] == -1)) {
alert(config.messages.invalidFileError.format([localPath]));
return;
}
bidix.WebDAVSaving.mkbackupfolder(null,null,params,original,posDiv);
};
// get original
var originalPath = document.location.toString();
if (originalPath.charAt(originalPath.length-1) == "/")
originalPath = originalPath + bidix.WebDAVSaving.defaultFilename;
displayMessage(bidix.WebDAVSaving.messages.aboutToSaveOnHttpDav.format([originalPath]));
doHttp("GET",originalPath,null,null,null,null,callback,originalPath,null);
};
bidix.WebDAVSaving.mkbackupfolder = function(root,dirs,url,original,posDiv) {
if (!root || !dirs) {
root = bidix.dirname(url);
if (config.options.txtBackupFolder == "")
dirs = null;
else
dirs = config.options.txtBackupFolder.split('/');
}
if (config.options.chkSaveBackups && dirs && (dirs.length > 0))
bidix.WebDAVSaving.mkdir(root,dirs.shift(),dirs,url,original,posDiv);
else
bidix.WebDAVSaving.saveBackup(url,original,posDiv);
};
bidix.WebDAVSaving.saveBackup = function(url,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if (!status) {
alert(config.messages.backupFailed);
return;
}
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
displayMessage(config.messages.backupSaved,url);
bidix.WebDAVSaving.saveRss(params[0],params[1],params[2]);
};
if(config.options.chkSaveBackups) {
var backupPath = getBackupPath(url);
bidix.httpPut(backupPath,original,callback,Array(url,original,posDiv));
} else {
bidix.WebDAVSaving.saveRss(url,original,posDiv);
}
}
bidix.WebDAVSaving.saveRss = function(url,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if (!status) {
alert(config.messages.rssFailed);
return;
}
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
displayMessage(config.messages.rssSaved,url);
bidix.WebDAVSaving.saveEmpty(params[0],params[1],params[2]);
};
if(config.options.chkGenerateAnRssFeed) {
var rssPath = url.substr(0,url.lastIndexOf(".")) + ".xml";
bidix.httpPut(rssPath,convertUnicodeToUTF8(generateRss()),callback,Array(url,original,posDiv));
} else {
bidix.WebDAVSaving.saveEmpty(url,original,posDiv);
}
}
bidix.WebDAVSaving.saveEmpty = function(url,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if (!status) {
alert(config.messages.emptyFailed);
return;
}
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
displayMessage(config.messages.emptySaved,url);
bidix.WebDAVSaving.saveMain(params[0],params[1],params[2]);
};
if(config.options.chkSaveEmptyTemplate) {
var emptyPath,p;
if((p = url.lastIndexOf("/")) != -1)
emptyPath = url.substr(0,p) + "/empty.html";
else
emptyPath = url + ".empty.html";
var empty = original.substr(0,posDiv[0] + startSaveArea.length) + original.substr(posDiv[1]);
bidix.httpPut(emptyPath,empty,callback,Array(url,original,posDiv));
} else {
bidix.WebDAVSaving.saveMain(url,original,posDiv);
}
}
bidix.WebDAVSaving.saveMain = function(url,original,posDiv)
{
var callback = function(status,params,responseText,url,xhr) {
if(status) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
displayMessage(config.messages.mainSaved,url);
store.setDirty(false);
} else
alert(config.messages.mainFailed);
};
// Save new file
var revised = updateOriginal(original,posDiv);
bidix.httpPut(url,revised,callback,null);
}
// asynchronous mkdir
bidix.WebDAVSaving.mkdir = function(root,dir,dirs,url,original,posDiv) {
var callback = function(status,params,responseText,url,xhr) {
url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
if (status == null) {
alert("Error in mkdir");
return;
}
if (xhr.status == httpStatus.ContentCreated) {
displayMessage(bidix.WebDAVSaving.messages.folderCreated.format([url]),url);
bidix.WebDAVSaving.mkbackupfolder(url,params[1],params[2],params[3],params[4]);
} else {
if (xhr.status == httpStatus.NotFound)
bidix.http('MKCOL',url,null,callback,params);
else
bidix.WebDAVSaving.mkbackupfolder(url,params[1],params[2],params[3],params[4]);
}
};
if (root.charAt(root.length) != '/')
root = root +'/';
bidix.http('HEAD',root+dir,null,callback,Array(root,dirs,url,original,posDiv));
}
bidix.httpPut = function(url,data,callback,params)
{
return bidix.http("PUT",url,data,callback,params);
}
bidix.http = function(type,url,data,callback,params)
{
var r = doHttp(type,url,data,null,null,null,callback,params,null);
if (typeof r == "string")
alert(r);
return r;
}
bidix.dirname = function (filePath) {
if (!filePath)
return;
var lastpos;
if ((lastpos = filePath.lastIndexOf("/")) != -1) {
return filePath.substring(0, lastpos);
} else {
return filePath.substring(0, filePath.lastIndexOf("\\"));
}
};
//}}}
This site includes refactored and rewritten BidiX's extensions compatible with the new TiddlyWiki <<version>>. If you are searching for plugins for previous version of TiddlyWiki, have a look at http://TiddlyHost.bidix.info/BidXTW21/
Currently the available extensions are :
*HistoryPlugin : Limits to only one tiddler open. Manages an history stack and provides macro to navigate in this history.
*[[UploadTiddler]] : per tiddler ''upload'' and ''save to web'' extension full compatible with UploadPlugin
*[[UploadPlugin 4.1]] : a refactored version of UploadPlugin with a Backstage entry.
*[[RSSReaderPlugin|RSSReaderPluginDescription]] : an RSSReader for TiddlyWiki
*[[GenerateRssByTag]] : only tiddlers tagged with a specific tag are added to the RSSFeed
*[[RSSReaderService]] : Display an RSSFeed in one page
*[[IsDirtyPlugin]] : an indicator for saving. see [[Need to be saved ?]]
*ProxyService : access a remote url even if TiddlyWiki is viewed over HTTP
*DownloadService : a script to download a TiddlyWiki in one click.
*[[PasswordOptionPlugin|PasswordOption]] : that extends the core Options with a non encrypted password type
*--[[WebDAVSavingPlugin|WebDAVSaving]] : the "save to web" function without script-- Not maintained : Use SaqImtiaz [[WebDavPlugin|http://tw.lewcid.org/#WebDavPlugin]]
See [[Extension directory]] for a full list.
''NEW: ''
* @@iTW 1.3.0 : TiddlyWiki for iPhone available at http://itw.bidix.info/@@
* UploadTiddlerPlugin and [[storeTiddler.php]] for a per tiddler Upload. Full compatible with UploadPlugin
----
<<tiddler [[Stay tuned]]>>
<<rssReader asHtml http://rss.news.yahoo.com/rss/sports>>
Type the text for 'New Tiddler'
tiddlywiki.abego-software.de
tiddlywiki.bidix.info
bob.mcelrath.org
gimcrackd.com
jackparke.googlepages.com
tw.lewcid.org
mptw.tiddlyspot.com
bradleymeck.tiddlyspot.com
solo.dc3.com
sra.sharedrecords.org
www.socialtext.net
tiddlystyles.com
www.tiddlytools.com
www.tiddlywiki.com
www.wikipedia.org
demo.zimbra.com
news.com.com
www.lemonde.fr
www.lesechos.fr
www.liberation.fr
www.nytimes.com
rss.news.yahoo.com
del.icio.us
<html><iframe style="border: 1px; background: #ccc;" width="100%" height="500" src="backup"></iframe></html>
<<rssReader asText http://del.icio.us/rss/tiddlywikiplugin>>
<?php
//{{{
/***
* download.php - download an html file as an attachement.
* version:1.1.1 - 2008/08/22 - BidiX@BidiX.info
* source: http://tiddlywiki.bidix.info/#download.php
* license: BSD open source license (http://tiddlywiki.bidix.info/#[[BSD open source license]])
*
* Simply put [[download|download.php?]] in your TiddlyWiki viewed over http to download it in one click*.
* * If it is named index.html
* usage :
* http://host/path/to/download.php[?file=afile.html|?help]
* afile.html : for security reason, must be a file with an .html suffix
* ?file=afile.html : if not specified index.html is used
* ?help : display the "usage" message
*
* each external javascript file is included in the downloaded file
***/
function display($msg) {
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>BidiX.info - TiddlyWiki - download script</title>
</head>
<body>
<p>
<p>download.php V 1.1.0
<p>BidiX@BidiX.info
<p> </p>
<p> </p>
<p> </p>
<p align="center"><?=$msg?></p>
<p align="center">Usage : http://<?=$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']?>[?file=<i>afile.html</i>]. If no file is specified uses index.html</p>
<p align="center">for details see : <a href="http://TiddlyWiki.bidix.info/#download.php">TiddlyWiki.bidix.info/#download.php<a>.</p>
</body>
</html>
<?php
return;
}
/*
* Recusrsively for each external javascript
* - Insert a comment : DOWNLOAD-INSERT-FILE
* - insert the content of the file
*/
function insertJSFileIn($content) {
// if (preg_match ('<script\s+type=\"text\/javascript\"\s+src=\"')) {
if (preg_match ('/<script\s+type=\"text\/javascript\"\s+src=\"/ms', $content)) {
if (preg_match ('/^(.*?)<script\s+type=\"text\/javascript\"\s+src=\"(.+?)\"\s*>\s*<\/script>(.*)$/ms', $content,$matches)) {
$front = $matches[1];
$js = $matches[2];
$tail = $matches[3];
$jsContent = "<!--DOWNLOAD-INSERT-FILE:\"$js\"--><script type=\"text/javascript\">" .
file_get_contents ($js) .
"\n</script>";
$tail = insertJSFileIn($tail);
return($front.$jsContent.$tail);
}
}
return $content;
}
/*
* Main
*/
// help command
if (array_key_exists('help',$_GET)) {
display('');
exit;
}
// file command
$filename = $_GET['file'];
if ($filename == "") {
$filename='index.html';
}
if (!preg_match('/\.html$/',$filename )) {
display("The file $filename could not be downloaded. Only .html file are allowed.");
exit;
}if (!is_file($filename)) {
display("The file $filename could not be found.");
exit;
}
$content = insertJSFileIn(file_get_contents ($filename));
//return the file
header('Pragma: private');
header('Cache-control: private, must-revalidate');
header('Content-type: text/html');
header('Content-Disposition: attachment; filename='.$filename);
echo($content);
//}}}
?>
<?php
//{{{
/***
* news.php - Display a RSS file using a CSS
* Copyright (c) 2006-2007, BidiX@BidiX.info
* version: 2.0.1 - 2007/05/13 - BidiX@BidiX.info
* source: http://tiddlywiki.bidix.info/#news.php
* license: BSD open source license (http://tiddlywiki.bidix.info/#[[BSD open source license]])
*
* usage :
* GET
* news.php[?[rss=<rssfile>[&css=<cssfile>][&encoding=<encoding>]]
* <rssfile>: a RSSFeed (default index.xml)
* <cssfile>: a CssFile (default embeded css)
* <encoding>: charset encoding of the feed (default 'utf-8')
*
* Revision history
* v 2.0.1 - 2007/05/13
* small css tweak
* v 2.0.0 - 2007/03/10
* should parse all RSS 2.0 feed
* embed a simple stylesheet
* v 1.0.1 - 2006/11/02 :
* minor enhancements
* v 1.0.0 - 2006/04/20 :
* design for GenerateRssHijack
*
***/
//
// parameters
//
$RSSFEED = 'index.xml';
$CSS = '';
$ENCODING = 'utf-8'; //'utf-8' 'iso-8859-1'
if (isset($_GET['rss'])) {
$RSSFEED = $_GET['rss'];
}
if (isset($_GET['css'])) {
$CSS = $_GET['css'];
}
if (isset($_GET['encoding'])) {
$ENCODING = $_GET['encoding'];
}
//
// Parser
//
class RSSParser {
// state
var $insideitem = false;
var $insideHeader = false;
var $tag = "";
// feed header
var $feedTitle = '';
var $feedDescription = '';
var $feedLink = '';
// items
var $items = array();
// current item
var $title = "";
var $description = "";
var $link = "";
// parser
var $xml_parser;
var $fp;
function __construct($url) {
global $ENCODING;
$this->xml_parser = xml_parser_create($ENCODING);
xml_set_object($this->xml_parser,$this);
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
xml_set_character_data_handler($this->xml_parser, "characterData");
$this->url = $url;
$this->fp = fopen($url,"r") or die("Error reading RSS data.");
}
function startElement($parser, $tagName, $attrs) {
$this->tag = $tagName;
if ($tagName == "ITEM") {
//end of header and beginning of item
$this->insideHeader = false;
$this->insideitem = true;
} elseif ($tagName == 'CHANNEL') {
//beginning of header
$this->insideHeader = true;
}
}
function endElement($parser, $tagName) {
if ($tagName == "ITEM") {
$this->items[] = array($this->title, $this->description, $this->link);
$this->title = "";
$this->description = "";
$this->link = "";
$this->insideitem = false;
}
}
function characterData($parser, $data) {
if (preg_match('/^\s*$/',$data))
return;
if ($this->insideitem) {
switch ($this->tag) {
case "TITLE":
$this->title .= $data;
break;
case "DESCRIPTION":
$this->description .= $data;
break;
case "LINK":
$this->link .= $data;
break;
}
}
elseif ($this->insideHeader) {
switch($this->tag) {
case 'TITLE':
$this->feedTitle .= $data;
break;
case 'DESCRIPTION':
$this->feedDescription .= $data;
break;
case 'LINK':
$this->feedLink .= $data;
break;
}
}
}
function parse() {
global $ENCODING;
while ($data = fread($this->fp, 4096))
xml_parse($this->xml_parser, utf8_html_entity_decode($data, $ENT_NOQUOTES, 'UTF-8'), feof($this->fp))
or die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)))
;
fclose($this->fp);
xml_parser_free($this->xml_parser);
}
//
// print
//
function printItem($title, $description, $link) {
print("<div class=\"feedItem\">");
//title
printf("<div class=\"itemTitle\"><a href='%s'>%s</a></div>",
trim($link),trim($title));
// description
printf("<div class=\"itemDescription\">%s</div>",$description);
print("</div>");
}
function printItems() {
foreach ($this->items as $item) {
$this->printItem($item[0], $item[1], $item[2]);
}
}
}
//
// Utilities for entity_decode (see: http://www.php.net/manual/en/function.html-entity-decode.php)
//
function utf8_replaceEntity($result){
$value = (int)$result[1];
$string = '';
$len = round(pow($value,1/8));
for($i=$len;$i>0;$i--){
$part = ($value & (255>>2)) | pow(2,7);
if ( $i == 1 ) $part |= 255<<(8-$len);
$string = chr($part) . $string;
$value >>= 6;
}
$string = html_entity_decode($string);
return $string;
}
function utf8_html_entity_decode($string){
return preg_replace_callback(
'/&#([0-9]+);/u',
'utf8_replaceEntity',
$string
);
}
//
// main
//
$rss_parser = new RSSParser($RSSFEED);
$rss_parser->__construct($RSSFEED);
$rss_parser->parse();
//
// Template HTML
//
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<meta name="description" content="<?=$rss_parser->feedTitle?> - <?=$rss_parser->feedDescription?>" />
<meta name="keywords" content="TiddlyWiki, RSS" />
<meta name="Generator" content="news.php - Copyright (C) 2007 BidiX@BidiX.info. All rights reserved." />
<meta name="robots" content="index, follow" />
<style type="text/css">
body {
font-size: .90em;
font-family: arial, helvetica, sans-serif;
padding: 30px;
}
h1,h2,h3,h4,h5,h1 {
font-weight: bold;
}
h1 {font-size: 1.35em;}
h2 {font-size: 1.25em;}
h3 {font-size: 1.1em;}
h4 {font-size: 1em;}
h5 {font-size: .9em;}
a img {border:0;}
#feedTitle {
font-size: 2em;
color: #BF2323;
}
#feedDescription {
font-size: 1,25em;
color: #666;
}
#items {
padding-left: 30px;
}
.feedItem {
padding-top: 1em;
padding-bottom: 1em;
border-top: solid 1px #ccc;
}
.itemTitle {
padding-bottom: 1em;
}
.itemTitle a {
font-size: 1.35em;
font-weight: bold;
color: #BF2323;
}
.itemDescription {
color: #666;
}
.itemDescription a {
color:#333;
}
</style>
<link rel="stylesheet" href="<?=$CSS?>" type="text/css" media="screen"/>
<BASE HREF="<?=$rss_parser->feedLink?>">
<title><?=$rss_parser->feedTitle?> - <?=$rss_parser->feedDescription?></title>
</head>
<body>
<div id="page">
<div id="header">
<h1 id="feedTitle"><?=$rss_parser->feedTitle?></h1>
<h2 id="feedDescription"><?=$rss_parser->feedDescription?></h2>
</div>
<div id='items'>
<?$rss_parser->printItems()?>
</div>
</div>
</body>
</html>
<?php
//}}}
?>
<?php
//{{{
/***
* [[proxy.php]] - access an url if the target host is allowed
* version: 2.2.0 - 2007/08/03 - BidiX@BidiX.info
* source: http://tiddlywiki.bidix.info/#proxy.php
* license: BSD open source license (http://tiddlywiki.bidix.info/#[[BSD open source license]])
* Copyright (c) BidiX@BidiX.info 2006-2007
*
* usage:
* proxy.php?url=<hostAndParameters>
* return the corresponding url if the host is included in the <ALLOWED_SITE_FILENAME> file
* or is in the same domain
* proxy.php?list
* list all allowedHosts
* proxy.cgi[?help]
* Display an help page
*
* require:
* <ALLOWED_SITE_FILENAME> a file located on the server containing a list af allowed hosts
* each host on a separate line.
* example :
* www.tiddlywiki.com
* tiddliwiki.bidix.info
* tiddlyspot.com
***/
$ALLOWED_SITE_FILENAME = '[[allowedsites.txt]]';
error_reporting(E_ERROR | E_PARSE);
function display($msg) {
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>BidiX.info - TiddlyWiki - proxy script</title>
</head>
<body>
<p>
<p>proxy.php V 2.2.0
<p>BidiX@BidiX.info
<p> </p>
<p> </p>
<p> </p>
<p align="center"><?=$msg?></p>
<p align="center">Usage : http://<?=$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']?>[?url=<i>URL</i>|help|list].</p>
<p align="center">for details see : <a href="http://TiddlyWiki.bidix.info/#proxy.php">TiddlyWiki.bidix.info/#proxy.php<a>.</p>
</body>
</html>
<?php
return;
}
function domain($host) {
// get last two segments of host name
// See : http://fr2.php.net/manual/en/function.preg-match.php#id5827438
preg_match('/[^.]+\.[^.]+$/', $host, $matches);
return $matches[0];
}
function inMyDomain($host) {
return (domain($_SERVER['HTTP_HOST']) == domain($host));
}
function isAllowed($host) {
global $ALLOWED_SITE_FILENAME;
// load allowed hosts
$allowedHosts = array_map('rtrim',file($ALLOWED_SITE_FILENAME));
if (!$allowedHosts) {
echo("allowedSites file '$ALLOWED_SITE_FILENAME' is not found or empty.");
exit;
}
return in_array($host, $allowedHosts);
}
/*
* Main
*/
// help command
if (array_key_exists('help',$_GET)) {
display('');
exit;
}
// list command
if (array_key_exists('list',$_GET)) {
echo "<h3>Hosts allowed through this proxy :</h3>\n<ul>\n";
$allowedHosts = array_map('rtrim',file($ALLOWED_SITE_FILENAME));
foreach ($allowedHosts as $host)
echo("<li>$host</li>\n");
echo "</ul>\n";
exit;
}
// url command
//control url
$url = $_GET['url'];
if (!$url) {
display('');
exit;
}
if (substr($url, 0, 4) != 'http')
$url = 'http://'.$url;
$urlArray = parse_url($url);
if (!$urlArray) {
echo("URL '$url' is not well formed");
exit;
}
$host = strtolower($urlArray['host']);
if (isset($urlArray['port']))
$port = $urlArray['port'];
else
$port = '80';
$file = $urlArray['path'];
if (isset($urlArray['query']))
$file = $file.'?'.$urlArray['query'];
if (isset($urlArray['fragment']))
$file = $file.'#'.$urlArray['fragment'];
// is $host allowed ?
if (!inMyDomain($host) && !isAllowed($host)) {
echo("Host '$host' is not allowed.");
exit;
}
// GET $file at $host:$port
// grab $headers and $content
$fp = fsockopen($host, $port, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)\n";
} else {
$out = "GET $file HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$fheader = 1;
$headers = "";
$content_type = "";
$content = "";
while (!feof($fp)) {
$line = fgets($fp, 128);
//Grab the headers
if ($fheader == 1) {
if ($line == "\r\n") {
$fheader = 0;
} else {
//Assemble the headers
$headers .= $line;
//grab content_type
if (preg_match("/Content-Type: (\w+\/\w+)(.*)/i", $line, $matches)) {
$content_type = $line;
}
}
} else {
//Grab the page content
$content .= $line;
}
}
fclose($fp);
}
header($content_type);
echo ($content);
//}}}
<?php
/***
! User settings
Edit these lines according to your need
***/
//{{{
$AUTHENTICATE_USER = true; // true | false
$USERS = array(
'UserName1'=>'Password1',
'UserName2'=>'Password2',
'UserName3'=>'Password3'); // set usernames and strong passwords
$DEBUG = false; // true | false
$CLEAN_BACKUP = true; // during backuping a file, remove overmuch backups
$FOLD_JS = true; // if javascript files have been expanded during download the fold them
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//}}}
/***
!Code
No change needed under
***/
//{{{
/***
* store.php - upload a file in this directory
* version :1.6.1 - 2007/08/01 - BidiX@BidiX.info
*
* see :
* http://tiddlywiki.bidi.info/#UploadPlugin for usage
* http://www.php.net/manual/en/features.file-upload.php
* for details on uploading files
* usage :
* POST
* UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;uploadir=<uploaddir>;[debug=1];;]
* userfile <file>
* GET
*
* each external javascript file included by download.php is change by a reference (src=...)
*
* Revision history
* V1.6.1 - 2007/08/01
* Enhancement: Add javascript folding
* V1.6.0 - 2007/05/17
* Enhancement: Add backup management
* V1.5.2 - 2007/02/13
* Enhancement: Add optional debug option in client parameters
* V1.5.1 - 2007/02/01
* Enhancement: Check value of file_uploads in php.ini. Thanks to Didier Corbière
* V1.5.0 - 2007/01/15
* Correct: a bug in moving uploadFile in uploadDir thanks to DaniGutiérrez for reporting
* Refactoring
* V 1.4.3 - 2006/10/17
* Test if $filename.lock exists for GroupAuthoring compatibility
* return mtime, destfile and backupfile after the message line
* V 1.4.2 - 2006/10/12
* add error_reporting(E_PARSE);
* v 1.4.1 - 2006/03/15
* add chmo 0664 on the uploadedFile
* v 1.4 - 2006/02/23
* add uploaddir option : a path for the uploaded file relative to the current directory
* backupdir is a relative path
* make recusively directories if necessary for backupDir and uploadDir
* v 1.3 - 2006/02/17
* presence and value of user are checked with $USERS Array (thanks to PauloSoares)
* v 1.2 - 2006/02/12
* POST
* UploadPlugin[backupDir=<backupdir>;user=<user>;password=<password>;]
* userfile <file>
* if $AUTHENTICATE_USER
* presence and value of user and password are checked with
* $USER and $PASSWORD
* v 1.1 - 2005/12/23
* POST UploadPlugin[backupDir=<backupdir>] userfile <file>
* v 1.0 - 2005/12/12
* POST userfile <file>
*
* Copyright (c) BidiX@BidiX.info 2005-2007
***/
//}}}
//{{{
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
/*
* GET Request
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>BidiX.info - TiddlyWiki UploadPlugin - Store script</title>
</head>
<body>
<p>
<p>store.php V 1.6.1
<p>BidiX@BidiX.info
<p> </p>
<p> </p>
<p> </p>
<p align="center">This page is designed to upload a <a href="http://www.tiddlywiki.com/">TiddlyWiki<a>.</p>
<p align="center">for details see : <a href="http://TiddlyWiki.bidix.info/#HowToUpload">TiddlyWiki.bidix.info/#HowToUpload<a>.</p>
</body>
</html>
<?php
exit;
}
/*
* POST Request
*/
// Recursive mkdir
function mkdirs($dir) {
if( is_null($dir) || $dir === "" ){
return false;
}
if( is_dir($dir) || $dir === "/" ){
return true;
}
if( mkdirs(dirname($dir)) ){
return mkdir($dir);
}
return false;
}
function toExit() {
global $DEBUG, $filename, $backupFilename, $options;
if ($DEBUG) {
echo ("\nHere is some debugging info : \n");
echo("\$filename : $filename \n");
echo("\$backupFilename : $backupFilename \n");
print ("\$_FILES : \n");
print_r($_FILES);
print ("\$options : \n");
print_r($options);
}
exit;
}
function ParseTWFileDate($s) {
// parse date element
preg_match ( '/^(\d\d\d\d)(\d\d)(\d\d)\.(\d\d)(\d\d)(\d\d)/', $s , $m );
// make a date object
$d = mktime($m[4], $m[5], $m[6], $m[2], $m[3], $m[1]);
// get the week number
$w = date("W",$d);
return array(
'year' => $m[1],
'mon' => $m[2],
'mday' => $m[3],
'hours' => $m[4],
'minutes' => $m[5],
'seconds' => $m[6],
'week' => $w);
}
function cleanFiles($dirname, $prefix) {
$now = getdate();
$now['week'] = date("W");
$hours = Array();
$mday = Array();
$year = Array();
$toDelete = Array();
// need files recent first
$files = Array();
($dir = opendir($dirname)) || die ("can't open dir '$dirname'");
while (false !== ($file = readdir($dir))) {
if (preg_match("/^$prefix/", $file))
array_push($files, $file);
}
$files = array_reverse($files);
// decides for each file
foreach ($files as $file) {
$fileTime = ParseTWFileDate(substr($file,strpos($file, '.')+1,strrpos($file,'.') - strpos($file, '.') -1));
if (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon']) &&
($now['mday'] == $fileTime['mday']) &&
($now['hours'] == $fileTime['hours']))
continue;
elseif (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon']) &&
($now['mday'] == $fileTime['mday'])) {
if (isset($hours[$fileTime['hours']]))
array_push($toDelete, $file);
else
$hours[$fileTime['hours']] = true;
}
elseif (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon'])) {
if (isset($mday[$fileTime['mday']]))
array_push($toDelete, $file);
else
$mday[$fileTime['mday']] = true;
}
else {
if (isset($year[$fileTime['year']][$fileTime['mon']]))
array_push($toDelete, $file);
else
$year[$fileTime['year']][$fileTime['mon']] = true;
}
}
return $toDelete;
}
function replaceJSContentIn($content) {
if (preg_match ("/(.*?)<!--DOWNLOAD-INSERT-FILE:\"(.*?)\"--><script\s+type=\"text\/javascript\">(.*)/ms", $content,$matches)) {
$front = $matches[1];
$js = $matches[2];
$tail = $matches[3];
if (preg_match ("/<\/script>(.*)/ms", $tail,$matches2)) {
$tail = $matches2[1];
}
$jsContent = "<script type=\"text/javascript\" src=\"$js\"></script>";
$tail = replaceJSContentIn($tail);
return($front.$jsContent.$tail);
}
else
return $content;
}
// Check if file_uploads is active in php config
if (ini_get('file_uploads') != '1') {
echo "Error : File upload is not active in php.ini\n";
toExit();
}
// var definitions
$uploadDir = './';
$uploadDirError = false;
$backupError = false;
$optionStr = $_POST['UploadPlugin'];
$optionArr=explode(';',$optionStr);
$options = array();
$backupFilename = '';
$filename = $_FILES['userfile']['name'];
$destfile = $filename;
// get options
foreach($optionArr as $o) {
list($key, $value) = split('=', $o);
$options[$key] = $value;
}
// debug activated by client
if ($options['debug'] == 1) {
$DEBUG = true;
}
// authenticate User
if (($AUTHENTICATE_USER)
&& ((!$options['user']) || (!$options['password']) || ($USERS[$options['user']] != $options['password']))) {
echo "Error : UserName or Password do not match \n";
echo "UserName : [".$options['user']. "] Password : [". $options['password'] . "]\n";
toExit();
}
// make uploadDir
if ($options['uploaddir']) {
$uploadDir = $options['uploaddir'];
// path control for uploadDir
if (!(strpos($uploadDir, "../") === false)) {
echo "Error: directory to upload specifies a parent folder";
toExit();
}
if (! is_dir($uploadDir)) {
mkdirs($uploadDir);
}
if (! is_dir($uploadDir)) {
echo "UploadDirError : $uploadDirError - File NOT uploaded !\n";
toExit();
}
if ($uploadDir{strlen($uploadDir)-1} != '/') {
$uploadDir = $uploadDir . '/';
}
}
$destfile = $uploadDir . $filename;
// backup existing file
if (file_exists($destfile) && ($options['backupDir'])) {
if (! is_dir($options['backupDir'])) {
mkdirs($options['backupDir']);
if (! is_dir($options['backupDir'])) {
$backupError = "backup mkdir error";
}
}
$backupFilename = $options['backupDir'].'/'.substr($filename, 0, strrpos($filename, '.'))
.date('.Ymd.His').substr($filename,strrpos($filename,'.'));
rename($destfile, $backupFilename) or ($backupError = "rename error");
// remove overmuch backup
if ($CLEAN_BACKUP) {
$toDelete = cleanFiles($options['backupDir'], substr($filename, 0, strrpos($filename, '.')));
foreach ($toDelete as $file) {
$f = $options['backupDir'].'/'.$file;
if($DEBUG) {
echo "delete : ".$options['backupDir'].'/'.$file."\n";
}
unlink($options['backupDir'].'/'.$file);
}
}
}
// move uploaded file to uploadDir
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $destfile)) {
if ($FOLD_JS) {
// rewrite the file to replace JS content
$fileContent = file_get_contents ($destfile);
$fileContent = replaceJSContentIn($fileContent);
if (!$handle = fopen($destfile, 'w')) {
echo "Cannot open file ($destfile)";
exit;
}
if (fwrite($handle, $fileContent) === FALSE) {
echo "Cannot write to file ($destfile)";
exit;
}
fclose($handle);
}
chmod($destfile, 0644);
if($DEBUG) {
echo "Debug mode \n\n";
}
if (!$backupError) {
echo "0 - File successfully loaded in " .$destfile. "\n";
} else {
echo "BackupError : $backupError - File successfully loaded in " .$destfile. "\n";
}
echo("destfile:$destfile \n");
if (($backupFilename) && (!$backupError)) {
echo "backupfile:$backupFilename\n";
}
$mtime = filemtime($destfile);
echo("mtime:$mtime");
}
else {
echo "Error : " . $_FILES['error']." - File NOT uploaded !\n";
}
toExit();
//}}}
?>
<?php
/***
! User settings
Edit these lines according to your need
***/
//{{{
$AUTHENTICATE_USER = true; // true | false
$USERS = array(
'UserName1'=>'Password1',
'UserName2'=>'Password2',
'UserName3'=>'Password3'); // set usernames and strong passwords
$DEBUG = false; // true | false
$CLEAN_BACKUP = true; // during backuping a file, remove overmuch backups
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//}}}
/***
!Code
No change needed under
***/
//{{{
/***
* storeTiddler.php - upload a tiddler to a TiddlyWiki file in this directory
* version: 1.2.1 - 2008-05-06 - BidiX@BidiX.info
*
* tiddler is POST as <FORM> with :
* FORM =
* title=<the title of the tiddler>
* tiddler=<result of externalizeTiddler() : the div in StoreArea format>
* [oldTitle=<the previous title of the tiddler>]
* [fileName=<tiddlyWiki filename>] (default: index.html)
* [backupDir=<backupdir>] (default: .)
* [user=<user>] (no default)
* [password=<password>] (no default)
* [uploadir=<uploaddir>] (default: .)
* [debug=1]] (default: false)
* see :
* http://tiddlywiki.bidi.info/#UploadTiddlerPlugin for usage
* http://tiddlywiki.bidi.info/#UploadPlugin for parameter descriptions
* usage :
* POST FORM
* Update <tiddler> in <fileName> TiddlyWiki
* GET
* Display a form for
*
* Revision history
* V1.2.1 - 2008-05-06
* bug correction : Filename is always 'index.html'. The fileName variable isn't used to initialize tiddlyWiki filename.
* V1.2.0 - 2008-03-23
* Exclusive lock to serialize rewrite of file
* V1.1.0 - 2008/03/05
* Delete tiddler with oldTitle
* V1.0.0 - 2008/02/24
* First public Version
* V0.3.0 - 2008/02/23
* minor adjustments
* V0.2.0 - 2008/02/23
* Correction bug on large regex
* V0.1.0 - 2008/02/09
* Initial: First working version
* V0.0.1 - 2008/02/02
* Initial: Proof Of Concept
*
* Copyright (c) BidiX@BidiX.info 2005-2008
***/
//}}}
//{{{
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
/*
* GET Request
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>BidiX.info - TiddlyWiki UploadTiddlerPlugin - Store script</title>
</head>
<body>
<p>
<p>storeTiddler.php V 1.2.0
<p>BidiX@BidiX.info
<p> </p>
<p> </p>
<p> </p>
<p align="center">This page is designed to upload a <a href="http://www.tiddlywiki.com/#Tiddler">Tiddler<a>.</p>
<p align="center">for details see : <a href="http://TiddlyWiki.bidix.info/#HowToUpload">TiddlyWiki.bidix.info/#HowToUpload<a>.</p>
<hr>
<form action="storeTiddler.php" method=POST>
<center>
<table>
<tr>
<td align=RIGHT>Title:</td>
<td><input type=TEXT name="title" size=80></td>
</tr>
<tr>
<td align=RIGHT>Tiddler (in StoreArea format):</td>
<td><TEXTAREA NAME="tiddler" COLS=80 ROWS=10>
<div title="New Tiddler" modifier="BidiX" created="200802161401" tags="test" changecount="1">
<pre>Type the text for 'New Tiddler'</pre>
</div>
</TEXTAREA></td>
</tr>
<tr>
<td align=RIGHT>Old Title:</td>
<td><input type=TEXT name="oldTitle" size=80 value=''></td>
</tr>
<tr>
<td align=RIGHT>fileName:</td>
<td><input type=TEXT name="fileName" size=80></td>
</tr>
<tr>
<td align=RIGHT>backupDir:</td>
<td><input type=TEXT name="backupDir" size=80></td>
</tr>
<tr>
<td align=RIGHT>user:</td>
<td><input type=TEXT name="user" size=80></td>
</tr>
<tr>
<td align=RIGHT>password:</td>
<td><input type=TEXT name="password" size=80></td>
</tr>
<tr>
<td align=RIGHT>uploadir:</td>
<td><input type=TEXT name="uploadir" size=80></td>
</tr>
<tr>
<td align=RIGHT>debug:</td>
<td><input type=TEXT name="debug" size=80 value=1></td>
</tr>
</table>
<input type=SUBMIT align="CENTER" value="Upload tiddler">
</center>
</form>
</body>
</html>
<?php
exit;
}
/*
* POST Request
*/
/*
* Functions included from store.php
*/
// Recursive mkdir
function mkdirs($dir) {
if( is_null($dir) || $dir === "" ){
return false;
}
if( is_dir($dir) || $dir === "/" ){
return true;
}
if( mkdirs(dirname($dir)) ){
return mkdir($dir);
}
return false;
}
function toExit() {
global $DEBUG, $filename, $backupFilename, $options;
if ($DEBUG) {
echo ("\nHere is some debugging info : \n");
echo("\$filename : $filename \n");
echo("\$backupFilename : $backupFilename \n");
print ("\$_FILES : \n");
print_r($_FILES);
print ("\$options : \n");
print_r($options);
}
exit;
}
function ParseTWFileDate($s) {
// parse date element
preg_match ( '/^(\d\d\d\d)(\d\d)(\d\d)\.(\d\d)(\d\d)(\d\d)/', $s , $m );
// make a date object
$d = mktime($m[4], $m[5], $m[6], $m[2], $m[3], $m[1]);
// get the week number
$w = date("W",$d);
return array(
'year' => $m[1],
'mon' => $m[2],
'mday' => $m[3],
'hours' => $m[4],
'minutes' => $m[5],
'seconds' => $m[6],
'week' => $w);
}
function cleanFiles($dirname, $prefix) {
$now = getdate();
$now['week'] = date("W");
$hours = Array();
$mday = Array();
$year = Array();
$toDelete = Array();
// need files recent first
$files = Array();
($dir = opendir($dirname)) || die ("can't open dir '$dirname'");
while (false !== ($file = readdir($dir))) {
if (preg_match("/^$prefix/", $file))
array_push($files, $file);
}
$files = array_reverse($files);
// decides for each file
foreach ($files as $file) {
$fileTime = ParseTWFileDate(substr($file,strpos($file, '.')+1,strrpos($file,'.') - strpos($file, '.') -1));
if (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon']) &&
($now['mday'] == $fileTime['mday']) &&
($now['hours'] == $fileTime['hours']))
continue;
elseif (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon']) &&
($now['mday'] == $fileTime['mday'])) {
if (isset($hours[$fileTime['hours']]))
array_push($toDelete, $file);
else
$hours[$fileTime['hours']] = true;
}
elseif (($now['year'] == $fileTime['year']) &&
($now['mon'] == $fileTime['mon'])) {
if (isset($mday[$fileTime['mday']]))
array_push($toDelete, $file);
else
$mday[$fileTime['mday']] = true;
}
else {
if (isset($year[$fileTime['year']][$fileTime['mon']]))
array_push($toDelete, $file);
else
$year[$fileTime['year']][$fileTime['mon']] = true;
}
}
return $toDelete;
}
/*
* End Functions included from store.php
*/
/*
* parse and print a TiddlyWiki file
*/
Function readTiddlyWiki($tw) {
if (preg_match ("/(.*?<div id=\"storeArea\">.*?)(<div.*)/ms", $tw,$matches)) {
$head = $matches[1];
$h = $matches[2];
$tiddlers = array();
while (preg_match ("/(.*?)(<div title=\"(.*?)\".*?<\/div>)(.*)/ms", $h,$matches)) {
$h=$matches[4];
$tiddlers[$matches[3]] = $matches[2];
}
$tail = ltrim($h);
}
else {
echo("The file '$file' isn't a valid TiddlyWiki");
toExit();
}
return array($head, $tiddlers ,$tail);
}
Function writeTiddlyWiki($head,$tiddlers,$tail) {
$content = $head;
sort($tiddlers);
foreach ($tiddlers as $t => $c) {
$content .= $c . "\n";
}
$content .= $tail;
return $content;
}
// var definitions
$uploadDir = './';
$uploadDirError = false;
$backupError = false;
$backupFilename = '';
$filename = "index.html";
$destfile = $filename;
$options = $_POST; // for store.php name compatibility
// debug activated by client
if ($options['debug'] == 1) {
$DEBUG = true;
}
// authenticate User
if (($AUTHENTICATE_USER)
&& ((!$options['user']) || (!$options['password']) || ($USERS[$options['user']] != $options['password']))) {
echo "Error : UserName or Password do not match \n";
echo "UserName : [".$options['user']. "] Password : [". $options['password'] . "]\n";
toExit();
}
if ($options['fileName'])
$filename = $options['fileName'];
// make uploadDir
if ($options['uploaddir']) {
$uploadDir = $options['uploaddir'];
// path control for uploadDir
if (!(strpos($uploadDir, "../") === false)) {
echo "Error: directory to upload specifies a parent folder";
toExit();
}
if (! is_dir($uploadDir)) {
mkdirs($uploadDir);
}
if (! is_dir($uploadDir)) {
echo "UploadDirError : $uploadDirError - File NOT uploaded !\n";
toExit();
}
if ($uploadDir{strlen($uploadDir)-1} != '/') {
$uploadDir = $uploadDir . '/';
}
}
$destfile = $uploadDir . $filename;
// backup existing file
if (file_exists($destfile) && ($options['backupDir'])) {
if (! is_dir($options['backupDir'])) {
mkdirs($options['backupDir']);
if (! is_dir($options['backupDir'])) {
$backupError = "backup mkdir error";
}
}
$backupFilename = $options['backupDir'].'/'.substr($filename, 0, strrpos($filename, '.'))
.date('.Ymd.His').substr($filename,strrpos($filename,'.'));
copy($destfile, $backupFilename) or ($backupError = "rename error");
// remove overmuch backup
if ($CLEAN_BACKUP) {
$toDelete = cleanFiles($options['backupDir'], substr($filename, 0, strrpos($filename, '.')));
foreach ($toDelete as $file) {
$f = $options['backupDir'].'/'.$file;
if($DEBUG) {
echo "delete : ".$options['backupDir'].'/'.$file."\n";
}
unlink($options['backupDir'].'/'.$file);
}
}
}
if (file_exists($destfile)) {
$f = fopen($destfile,'r+');
if (flock($f, LOCK_EX)) {
while (!feof($f)) {
$contents .= fread($f, 8192);
}
list($head,$tiddlers,$tail) = readTiddlyWiki($contents);
$title = $_POST['title'];
$oldTitle = $_POST['oldTitle'];
if ($oldTitle && ($title != $oldTitle)) {
unset($tiddlers[$oldTitle]);
}
$tiddlers[$title] = stripslashes($_POST['tiddler']);
$contents = writeTiddlyWiki($head,$tiddlers,$tail);
if (!rewind($f)) {
echo("rewind error");
toExit();
}
if (!ftruncate($f, 0)) {
echo("ftruncate error");
toExit();
};
if (!fwrite($f, $contents)) {
echo("fwrite error");
toExit();
}
fclose($f); // fclose also unlock the file
if($DEBUG) {
echo "Debug mode \n\n";
}
if (!$backupError) {
echo "0 - Tiddler successfully updated in " .$destfile. "\n";
} else {
echo "BackupError : $backupError - Tiddler successfully updated in " .$destfile. "\n";
}
echo("destfile:$destfile \n");
if (($backupFilename) && (!$backupError)) {
echo "backupfile:$backupFilename\n";
}
$mtime = filemtime($destfile);
echo("mtime:$mtime");
}
else {
echo "Error : '" . $filename . "' couldn't be locked - File NOT updated !\n";
}
}
else {
echo "Error : '" . $filename . "' doesn't exist - File NOT updated !\n";
}
toExit();
?>
<<uploadTiddler>>
Test of uploadTiddler
//{{{
config.macros.version.handler = function(place)
{
createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : "") + (version.build ? " (build #" + version.build + ")" : ""));
};
readOnly = false;
config.options.chkBackstage = true;
config.macros.changeMode.lingo.modeName[''] = 'Admin';
config.options.txtRssTag = 'toRSS';
config.options.chkGenerateAnRssFeed = true;
//}}}