Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
/***
!Metadata:
|''Name:''|ArchivedTimeline|
|''Description:''|Timeline archived monthly.|
|''Version:''|0.7.0|
|''Date:''|Aug 25, 2007|
|''Source:''|http://sourceforge.net/project/showfiles.php?group_id=150646|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.0.11|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0|
!Syntax:
{{{<<timeline [modified|created [maxentries [dateFormate]]]>>}}}
!Examples:
{{{<<timeline>>}}}
{{{<<timeline created 10>>}}}
{{{<<timeline modified 10 "MMM DD, YYYY">>}}}
!Revision History:
|''Version''|''Date''|''Note''|
|0.7.0|Jul 25, 2006|Accept a date format parameter|
|0.6.3|Jan 14, 2007|Cleaned codes, Removed config.macros.timeline.slider and config.macros.timeline.onClickSlider|
|0.6.2|Dec 10, 2006|Add monthFormat to display month format for Chinese|
|0.6.1|Aug 12, 2006|A great effect on config.macros.timeline.slider for Firefox, thanks Bob McElrath|
|0.6.0|Jul 25, 2006|Runs compatibly with TW 2.1.0 (rev #403+)|
|0.5.2|Jun 21, 2006|Fixed bugs for dateFormat of TW 2.1|
|~|~|Change default dateFormat to "0DD MMM, YYYY"|
|0.5.1|Jun 04, 2006|Added config.macros.archivedTimeline.orderBy for localization|
|0.5.0|Apr 19, 2006|Fixed bug for twice records of the same date ()|
|~|~|Added Date.prototype.convertToLocalYYYYMMDDHHMM<<br>>in order to backward compatible with 2.0.6-|
|0.4.0|Apr 03, 2006|Added new parameter, {{{<<timeline [sortfield] [maxentries]>>}}}|
|~|~|Added config.options.txtTimelineMaxentries|
|0.3.1|Feb 04, 2006|JSLint checked|
|0.3.0|Feb 04, 2006|Fixed several missing variable declarations|
|0.2.0|Dec 26, 2005|changed for the new feature of Macro timeline of TW 2.0.0 beta 6|
|0.1.0|Nov 3, 2005|Initial release|
!Code section:
***/
//{{{
version.extensions.archivedTimeline = {major: 0, minor: 7, revision: 0,
date: new Date("Aug 26, 2007"),
name: "ArchivedTimeline",
type: "Macro",
author: "BramChen",
source: "http://sourceforge.net/project/showfiles.php?group_id=150646"
};
config.options.txtTimelineMaxentries=0;
config.macros.archivedTimeline = {
tooltips: "Archives sorted by ",
orderBy:{modified: "modified", created: "created"},
monthFormat: "0DD MMM YYYY",
dateFormat: "0DD MMM YYYY"
};
config.macros.timeline = config.macros.archivedTimeline;
config.macros.timeline.handler = function(place,macroName,params) {
var field = params[0] ? params[0] : "modified";
place.appendChild(document.createTextNode(this.tooltips + this.orderBy[field]));
var tiddlers = store.reverseLookup("tags","excludeLists",false,field);
var lastMonth = ""; var lastDay = ""; var theText = "----\n"; var i = 0;
var last = (params[1])?params[1]:config.options.txtTimelineMaxentries;
last = (isNaN(last)||last<1) ? 0:tiddlers.length-Math.min(tiddlers.length,parseInt(last));
var dateFormat = params[2] ? params[2] : this.dateFormat;
var cookie; var archives;
for (var t=tiddlers.length-1; t>=last; t--) {
var tiddler = tiddlers[t];
var theMonth = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,6);
var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
if(theMonth != lastMonth) {
if (lastMonth === "") {
lastMonth = theMonth;
}
else {
place.appendChild(document.createElement('hr'));
cookie = 'chktimeline'+(i++);
archives = this.formatString(this.monthFormat, lastMonth);
var panel = config.macros.slider.createSlider(place,cookie,archives,this.tooltips + archives);
wikify(theText,panel);
lastMonth = theMonth; theText = '----\n';
}
}
if(theDay != lastDay){
theText += tiddler[field].formatString(dateFormat) + '\n';
lastDay = theDay;
}
theText += '* [[' + tiddler.title + ']]\n';
}
place.appendChild(document.createElement('hr'));
cookie = 'chktimeline'+(i++);
archives = this.formatString(this.monthFormat, lastMonth);
var panel = config.macros.slider.createSlider(place,cookie,archives,this.tooltips + archives);
wikify(theText,panel);
place.appendChild(document.createElement('hr'));
};
config.macros.timeline.formatString = function(template, yyyymm)
{
var dateString = new Date(yyyymm.substr(0,4)+'/'+yyyymm.substr(4,2)+'/01');
template = template.replace(/DDD|0DD|DD/g,'');
return dateString.formatString(template);
};
if (!Date.prototype.convertToLocalYYYYMMDDHHMM){
Date.prototype.convertToLocalYYYYMMDDHHMM = function(){
return(String.zeroPad(this.getFullYear(),4) + String.zeroPad(this.getMonth()+1,2) + String.zeroPad(this.getDate(),2) + String.zeroPad(this.getHours(),2) + String.zeroPad(this.getMinutes(),2));
}
}
//}}}
/***
!! Collapse Plugins
^^Authors: Eric Shulman & Bradley Meck^^
***/
config.commands.collapseTiddler = {
text: " - ",
tooltip: "Collapse this tiddler",
handler: function(event,src,title)
{
var e = story.findContainingTiddler(src);
if(e.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){
var template;
if(e.getAttribute("template") != "CollapsedTemplate" ){
e.setAttribute("oldTemplate",e.getAttribute("template"));
story.displayTiddler(null,title,"CollapsedTemplate");
}
}
}
}
config.commands.expandTiddler = {
text: " + ",
tooltip: "Expand this tiddler",
handler: function(event,src,title)
{
var e = story.findContainingTiddler(src);
story.displayTiddler(null,title,e.getAttribute("oldTemplate"));
}
}
config.macros.collapseAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"Collapse All","",function(){
story.forEachTiddler(function(title,tiddler){
if(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE])
story.displayTiddler(null,title,"CollapsedTemplate");
})})
}
}
config.macros.expandAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"Expand All","",function(){
story.forEachTiddler(function(title,tiddler){
if(tiddler.getAttribute("template") == "CollapsedTemplate") story.displayTiddler(null,title,tiddler.getAttribute("oldTemplate"));
})})
}
}
config.commands.collapseOthers = {
text: "collapse others",
tooltip: "Expand this tiddler and collapse all others",
handler: function(event,src,title)
{
var e = story.findContainingTiddler(src);
story.forEachTiddler(function(title,tiddler){
if(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){
var t="CollapsedTemplate";
if (e==tiddler) t=e.getAttribute("oldTemplate");
if (!t||!t.length) t="ViewTemplate";
story.displayTiddler(null,title,t);
}
})
}
}
/***
|Name|CollapseTiddlersPlugin|
|Source|http://gensoft.revhost.net/Collapse.html|
|Version|2007.10.11|
|Author|Bradley Meck (modified by ELS)|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires|CollapsedTemplate|
|Overrides||
|Description|show/hide content of a tiddler while leaving tiddler title visible|
|ELS 10/11/2007: moved [[FoldFirst]] inline script and converted to {{{<<foldFirst>>}}} macro. |
|ELS 9/12/2007: suspend/resume SinglePageMode (SPM/TPM/BPM) when folding/unfolding tiddlers |
|ELS 6/5/2007: add "return false" at the end of each command handler to prevent IE 'page transition' problem. |
|ELS 3/30/2007: add a shadow definition for CollapsedTemplate. Tweak ViewTemplate shadow so "fold/unfold" and "focus" toolbar items automatically appear when using default templates. Remove error check for "CollapsedTemplate" existence, since shadow version will now always work as a fallback. |
|ELS 2/24/2006: added fallback to "CollapsedTemplate" if "WebCollapsedTemplate" is not found |
|ELS 2/6/2006: added check for 'readOnly' flag to use alternative "WebCollapsedTemplate" |
***/
//{{{
config.shadowTiddlers.CollapsedTemplate=
"<!--{{{-->\
<div class='toolbar' macro='toolbar expandTiddler collapseOthers closeTiddler closeOthers +editTiddler permalink references jump'></div>\
<div class='title' macro='view title'></div>\
<!--}}}-->";
// automatically tweak shadow ViewTemplate to add "collapseTiddler collapseOthers" commands at 'front' of toolbar (before 'closeTiddler')
config.shadowTiddlers.ViewTemplate=config.shadowTiddlers.ViewTemplate.replace(/closeTiddler/,"collapseTiddler collapseOthers closeTiddler");
config.commands.collapseTiddler = {
text: "fold",
tooltip: "Collapse this tiddler",
handler: function(event,src,title) {
var e = story.findContainingTiddler(src); if (!e) return false;
if(e.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]) {
var t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if(e.getAttribute("template") != t ){
e.setAttribute("oldTemplate",e.getAttribute("template"));
// suspend single page mode (or top/bottom of page mode)
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
// display tiddler
story.displayTiddler(null,title,t);
// restore SPM/TPM/BPM settings
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
}
}
return false;
}
}
config.commands.expandTiddler = {
text: "unfold",
tooltip: "Expand this tiddler",
handler: function(event,src,title) {
var e = story.findContainingTiddler(src); if (!e) return false;
// suspend single page mode (or top/bottom of page mode)
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
// display tiddler
story.displayTiddler(null,title,e.getAttribute("oldTemplate"));
// restore SPM/TPM/BPM settings
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
return false;
}
}
config.macros.collapseAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"Collapse All","",function(){
story.forEachTiddler(function(title,tiddler){
if(story.isDirty(tiddler.title)) return;
var t=(readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
// suspend single page mode (or top/bottom of page mode)
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
// display tiddler
story.displayTiddler(null,title,t);
// restore SPM/TPM/BPM settings
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
})
})
}
}
config.macros.expandAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"Expand All","",function(){
story.forEachTiddler(function(title,tiddler){
var t=(readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
// suspend single page mode (or top/bottom of page mode)
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
// display tiddler
if(tiddler.getAttribute("template") == t) story.displayTiddler(null,title,tiddler.getAttribute("oldTemplate"));
// restore SPM/TPM/BPM settings
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
})
})
}
}
config.commands.collapseOthers = {
text: "focus",
tooltip: "Expand this tiddler and collapse all others",
handler: function(event,src,title) {
var e = story.findContainingTiddler(src); if (!e) return false;
story.forEachTiddler(function(title,tiddler) {
if(story.isDirty(tiddler.title)) return;
var t=(readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (e==tiddler) t=e.getAttribute("oldTemplate");
// suspend single page mode (or top/bottom of page mode)
var saveSPM=config.options.chkSinglePageMode; config.options.chkSinglePageMode=false;
var saveTPM=config.options.chkTopOfPageMode; config.options.chkTopOfPageMode=false;
var saveBPM=config.options.chkBottomOfPageMode; config.options.chkBottomOfPageMode=false;
// display tiddler
story.displayTiddler(null,title,t);
// restore SPM/TPM/BPM settings
config.options.chkBottomOfPageMode=saveBPM;
config.options.chkTopOfPageMode=saveTPM;
config.options.chkSinglePageMode=saveSPM;
})
return false;
}
}
// {{{<<foldFirst>>}}} macro forces tiddler to be folded when initially displayed.
// Subsequent re-render does NOT re-fold tiddler, but closing/re-opening tiddler DOES cause it to fold first again.
config.macros.foldFirst = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
var here=story.findContainingTiddler(place);
if (here.foldedFirst) return; // already been folded
var template = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (!store.tiddlerExists(template)) { displayMessage("FoldFirst: can't find 'CollapsedTemplate'"); return; }
here.setAttribute("oldTemplate",here.getAttribute("template"));
story.displayTiddler(null,here.getAttribute("tiddler"),template);
here.foldedFirst=true; // only when tiddler is first rendered
return false;
}
}
//}}}
[[巴蛮子]]
[[TiddlyWiki: 单网页的Wiki, GTD和Blog系统]]
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler wikibar'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter' macro='deliciousTagging'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div class='editor' macro='edit text'></div>
<!--}}}-->
/*plugins for Authoring */
plugins\WikiBar2Plus.js
plugins\TidIDEPlugin.js
plugins\TiddlersBarPlugin.js
plugins\TiddlerTweakerPlugin.js
plugins\EasyEditPlugin.js
plugins\DeliciousTagging.js
/* others */
plugins\BigThemePack.js
plugins\SelectThemePlugin.js
plugins\Syntaxify.js
plugins\RearrangeTiddlersPlugin.js
plugins\ListExtensionsCode.js
现象: Firefox 3上访问Google Reader时,只显示顶部的一些链接,那个黄色的"loading"就一直不消失,内容也就出不来
原因: 禁用Firebugs扩展即可
定位方法:
#开始看见"loading"一直在,以为跟Google Mail一样,是网速问题导致内容无法显示出来;
#后来逐渐发现Firefox 2上没有问题;
#在Google上搜索"Firefox 3 Google Reader"没有什么有效结果,看来不是使用Firefox 3的人都有这问题
#试验Firefox的"安全模式",正常了,看来是扩展的问题
# 对扩展使用折半定位: 先禁用一半扩展,重启Fx,看是否有问题,有问题则将被禁用的扩展缩小一半再试,没问题就将未被禁用的扩展减少一般再试。这样我的20多个扩展,只要5次就可以定位出来了:是Firebug!
另外,家里的机器上用Firefox 3访问Google Reader就崩溃,不知道为啥,从beta 2到beta 4一直有这个问题(每出一个beta版本我都会试一下)
目前还有很多插件不支持Firefox 3,如果你实在想用,可以修改下面两个设置:
{{{
user_pref("extensions.checkCompatibility", false);
user_pref("extensions.checkUpdateSecurity", false);
}}}
这样Firefox升级或者安装新扩展时就不会检查兼容性和签名了(检查扩展的签名是Fx3新增的功能)。不过扩展不一定能正常工作,比如Google工具栏就不成。
可以将这两行加在profile下prefs.js(请先关闭Firefox),也可以在about:config中手工增加这两项。
以前我为了几台机器、几个操作系统上书签的同步烦心不已,即使安装了[[Foxmarks同步器|http://addons.mozilla.org/en-US/firefox/addon/2410]]还得留神用哪个覆盖哪个,而Google工具栏提供的书签功能也不太好用。后来开始使用del.icio.us的书签服务,加上[[del.icio.us Bookmarks扩展|http://addons.mozilla.org/en-US/firefox/addon/3615]],终于很满意了。
但[[Firefox 3出来了beta 1|http://www.mozilla.com/firefox/all-beta.html]]之后,我就基本上开始用新版本了,毕竟很多功能很不错,内存占用比原来少了(也许是目前安装的扩展还比较少),再说反正以后要切的。不过目前还是两个版本都用。
但目前很多扩展都还不支持Firefox 3(而且Firefox 3开始要求对扩展进行签名了,不能象以前那样简单地下载xpi包后自己来改改版本匹配申明就说不定可以使用),有些扩展倒也罢了,但现在del.icio.us 似乎变成必须了 :-)
查看/搜索书签的功能倒简单,只要访问 http://del.icio.us/home 就可以了,网页上也有输入tag进行搜索的功能。
主要的问题是没法方便地添加书签了,以前只要在网上逛,看到不错的地方,按一下Ctrl+D或者点击工具栏的TAG按钮,就有一个对话框出来,当前网页的标题、其他人的tag都显示出来了,并且当前网页选中的文字还可以自动放入书签的说明栏。
[img[Add Tag button for del.icio.us|http://images.del.icio.us/static/img/help/firefox/bookmarks/overBookmarking.jpg]]
在del.icio.us的帮助中找了一下,发现可以用如下办法: 在书签栏上添加一个书签,其URL是:
javascript:location.href='http://del.icio.us/post?v=4;url='+encodeURIComponent(location.href)+';title='+encodeURIComponent(document.title)
(可以拖这个链接到书签栏,然后自己改名字)
详细的说明在这里: [[bookmarklet buttons for any browser|http://del.icio.us/help/buttons]]
但“当前网页选中的文字还可以自动放入书签的说明栏”这一点还不能做到,不太爽。我试验了一下,发现多传一个notes参数就可以了: 在上述URL后面再添加一节:
+';notes='+encodeURIComponent(window.getSelection().toString())
结论: 拖下面这个链接到书签栏就可以了:
<html>
<a href="javascript:location.href='http://del.icio.us/post?v=4;url='+encodeURIComponent(location.href)+';title='+encodeURIComponent(document.title)+';notes='+encodeURIComponent(window.getSelection().toString())">
post to del.icio.us
</a></html>
/***
|Name|FullScreenPlugin|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#FullScreenPlugin|
|Version|1.1|
|Requires|~TW2.x|
!Description:
Toggle between viewing tiddlers fullscreen and normally. Very handy for when you need more viewing space.
!Demo:
Click the ↕ button in the toolbar for this tiddler. Click it again to turn off fullscreen.
!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.
Edit the ViewTemplate to add the fullscreen command to the toolbar.
!History:
*25-07-06: ver 1.1
*20-07-06: ver 1.0
!Code
***/
//{{{
var lewcidFullScreen = false;
config.commands.fullscreen =
{
text:" «FullScreen» ",
tooltip:"Fullscreen mode"
};
config.commands.fullscreen.handler = function (event,src,title)
{
if (lewcidFullScreen == false)
{
lewcidFullScreen = true;
setStylesheet('#sidebar, .header , #mainMenu{display:none;} #displayArea{margin:0em 0 0 0 !important;}',"lewcidFullScreenStyle");
}
else
{
lewcidFullScreen = false;
setStylesheet(' ',"lewcidFullScreenStyle");
}
}
config.macros.fullscreen={};
config.macros.fullscreen.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var label = params[0]||" «Screen» ";
var tooltip = params[1]||"Fullscreen mode";
createTiddlyButton(place,label,tooltip,config.commands.fullscreen.handler);
}
var lewcid_fullscreen_closeTiddler = Story.prototype.closeTiddler;
Story.prototype.closeTiddler =function(title,animate,slowly)
{
lewcid_fullscreen_closeTiddler.apply(this,arguments);
if (story.isEmpty() && lewcidFullScreen == true)
config.commands.fullscreen.handler();
}
Slider.prototype.lewcidStop = Slider.prototype.stop;
Slider.prototype.stop = function()
{
this.lewcidStop();
if (story.isEmpty() && lewcidFullScreen == true)
config.commands.fullscreen.handler();
}
//}}}
使用此 TiddlyWiki 的空白模版之前,请先修改以下默认文章:
* SiteTitle 及 SiteSubtitle:网站的标题和副标题,显示于页面上方<br />(在保存变更后,将显示于浏览器视窗的标题列)。
* MainMenu:主菜单(通常在页面左侧)。
* DefaultTiddlers:包含一些文章的标题,可于进入TiddlyWiki 后开启。
请输入您的大名,作为所创建/ 编辑文章的署名:<<option txtUserName>>
/***
|Name|GotoPlugin|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.5.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|view any tiddler by entering it's title - displays list of possible matches|
''View a tiddler by typing its title and pressing //enter//.'' As you type, a list of possible matches is displayed. You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press //escape// to close the listbox to resume typing. When the listbox is ''//not//'' being displayed, press //escape// to clear the current text input and start over.
!!!!!Documentation
>see [[GotoPluginInfo]]
!!!!!Revisions
<<<
2008.02.17 [1.5.0] ENTER key always displays tiddler based on current input regardless of whether input matches any existing tiddler
|please see [[GotoPluginInfo]] for additional revision details|
2006.05.05 [0.0.0] started
<<<
!!!!!Code
***/
//{{{
version.extensions.gotoTiddler = {major: 1, minor: 5, revision: 0, date: new Date(200,2,17)};
// automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");
config.macros.gotoTiddler= {
handler:
function(place,macroName,params) {
var quiet=(params[0] && params[0]=="quiet"); if (quiet) params.shift();
var insert=(params[0] && params[0]=="insert"); if (insert) params.shift();
var instyle=params.shift(); if (!instyle) instyle="";
var liststyle=params.shift(); if (!liststyle) liststyle="";
var keyevent=window.event?"onkeydown":"onkeypress";
createTiddlyElement(place,"span").innerHTML
=this.html.replace(/%keyevent%/g,keyevent).replace(/%insert%/g,insert).replace(/%quiet%/g,quiet).replace(/%instyle%/g,instyle).replace(/%liststyle%/g,liststyle);
},
html:
'<form onsubmit="return false" style="display:inline;margin:0;padding:0">\
<input name=gotoTiddler type=text autocomplete="off" accesskey="G" style="%instyle%"\
title="enter a tiddler title"\
onclick="this.form.list.style.display=\'none\';"\
onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list);"\
onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,this.form.list,%quiet%,%insert%);">\
<select name=list style="%liststyle%;display:none;position:absolute"\
onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
onblur="this.style.display=\'none\';"\
%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler,%insert%);"\
onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this,%insert%);">\
</select>\
</form>',
getItems:
function(val) {
if (!this.items.length || val.length<2) { // starting new search, refresh cached list of tiddlers/shadows/tags
this.items=new Array();
var tiddlers=store.getTiddlers("title","excludeLists");
for(var t=0; t<tiddlers.length; t++) this.items.push(tiddlers[t].title);
for (var t in config.shadowTiddlers) this.items.pushUnique(t);
var tags=store.getTags();
for(var t=0; t<tags.length; t++) this.items.pushUnique(tags[t][0]);
}
var found = [];
var match=val.toLowerCase();
for(var i=0; i<this.items.length; i++)
if (this.items[i].toLowerCase().indexOf(match)!=-1) found.push(this.items[i]);
return found;
},
items: [], // cached list of tiddlers/shadows/tags
getItemSuffix:
function(t) {
if (store.tiddlerExists(t)) return ""; // tiddler
if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
return " (tag)"; // tag
},
keyProcessed:
function(ev) { // utility function: exits handler and prevents browser from processing the keystroke
ev.cancelBubble=true; // IE4+
try{event.keyCode=0;}catch(e){}; // IE5
if (window.event) ev.returnValue=false; // IE6
if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
if (ev.stopPropagation) ev.stopPropagation(); // all
return false;
},
inputEscKeyHandler:
function(event,here,list) {
var key=event.keyCode;
// escape... hide list (2nd esc=clears input)
if (key==27) {
if (list.style.display=="none")
here.value=here.defaultValue;
list.style.display="none";
return this.keyProcessed(event);
}
return true; // key bubbles up
},
inputKeyHandler:
function(event,here,list,quiet,insert) {
var key=event.keyCode;
// non-printing chars... bubble up, except: backspace=8, enter=13, space=32, down=40, delete=46
if (key<48) switch(key) { case 8: case 13: case 32: case 40: case 46: break; default: return true; }
// blank input... if down/enter... fall through (list all)... else, and hide list
if (!here.value.length && !(key==40 || key==13))
{ list.style.display="none"; return this.keyProcessed(event); }
// find matching items...
var found = this.getItems(here.value);
// non-blank input... enter key... show/create tiddler
if (key==13) return this.processItem(here.value,here,list,insert);
// make sure list is shown/hidden
list.style.display=(!quiet && found.length)?"block":"none";
// no matches, key bubbles up
if (!found.length) return true;
// down key... shows/moves to list...
if (key==40) { list.style.display="block"; list.focus(); }
// finally, if list is showing, fill it with found results...
if (list.style.display!="none") {
while (list.length > 0) list.options[0]=null; // clear list
found.sort(); // alpha by title
var hdr=this.listHeading.format([found.length,found.length==1?"":"s"]);
list.options[0]=new Option(hdr,"",false,false);
for (var t=0; t<found.length; t++) // fill list...
list.options[list.length]=new Option(found[t]+this.getItemSuffix(found[t]),found[t],false,false);
list.size=(found.length<this.listMaxSize?found.length:this.listMaxSize)+1; // resize list...
list.selectedIndex=(key==40 || key==13)?1:0;
}
return true; // key bubbles up
},
listMaxSize: 10,
listHeading: 'Found %0 matching title%1:',
selectKeyHandler:
function(event,list,editfield,insert) {
if (event.keyCode==27) // escape... hide list, move to edit field
{ editfield.focus(); list.style.display="none"; return this.keyProcessed(event); }
if (event.keyCode==13 && list.value.length) // enter... view selected item
{ this.processItem(list.value,editfield,list,insert); return this.keyProcessed(event); }
return true; // key bubbles up
},
processItem:
function(title,here,list,insert) {
if (!title.length) return; here.value=title; list.style.display='none';
if (insert) {
var tidElem=story.findContainingTiddler(here); if (!tidElem) { here.focus(); return false; }
var e=story.getTiddlerField(tidElem.getAttribute("tiddler"),"text");
if (!e||e.getAttribute("edit")!="text") return false;
var txt=prompt(this.askForText,title); if (!txt||!txt.length) { here.focus(); return false; }
e.focus(); // put focus on target field before setting selection
replaceSelection(e,"[["+txt+"|"+title+"]]"); // insert selected tiddler as a PrettyLink
}
else
story.displayTiddler(null,title); // show selected tiddler
return false;
},
askForText: "Enter the text to display for this link"
}
//}}}
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2008.02.23 [1.9.1] in onclick function, use string instead of array for 'bufferedHTML' attribute on link element (fixes IE errors)
2008.02.21 [1.9.0] 'onclick' scripts now allow returned text (or document.write() calls) to be wikified into a span that immediately follows the onclick link. Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed). Thanks to Xavier Verges for suggestion and preliminary code.
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.inlineJavascript= {major: 1, minor: 9, revision: 1, date: new Date(2008,2,23)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // load a script library
// make script tag, set src, add to body to execute, then remove for cleanup
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // there is script code
if (show) // show inline script code in tiddler output
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create a link to an 'onclick' script
// add a link, define click handler, save code in link (pass 'place'), set link attributes
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place){"+fixup+"\n};_out(this);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run inline script code
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var code="function _out(place){"+fixup+"\n};_out(w.output);"
try { var out=eval(code); } catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") function wikifyPlainText(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
闭包这个概念随着并发、函数式编程的复兴,也热乎了起来。”[[跟上Java闭包(Closure)的步伐|http://www.infoq.com/cn/news/2007/09/catching-up-with-closures]]“一文中说:
<<<
Mark Jason Dominus在[[Perl概述|http://www.theperlreview.com/Interviews/mjd-hop-20050407.html]]中的话语作为开场:在未来的三十年中,人们将会取笑那些发明没有闭包特性的语言的人,如同他们现在正取笑那些发明没有递归这种特性的语言的人是一个道理。
<<<
* 定义
那么这是个啥东西? Wikipedia上对closure的解释是:
<<<
In computer science, a closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables. The explicit use of closures is associated with functional programming and with languages such as ML and Lisp. Constructs such as objects in other languages can also be modeled with closures.
In some languages, a closure may occur when a function is defined within another function, and the inner function refers to local variables of the outer function. At runtime, when the outer function executes, a closure is formed, consisting of the inner function’s code and references to any variables of the outer function required by the closure.
<<<
这个说法比较抽象。还是来看看实际的例子吧。
* 实例说明
在JavaScript中,简单的说法是: __In JavaScript, if you use the function keyword inside another function, you are creating a closure__.(摘自Morris Johns的[[JavaScript Closures for Dummies|http://blog.morrisjohns.com/javascript_closures_for_dummies]], 中文翻译可看这里: [[在JavaScript中,什么是闭包|http://javascript.chinahtml.com/2006/javascript-11607091807203.shtml]])。
//{{{
function sayHello(name) {
var text = 'Hello ' + name; // local variable
var sayAlert = function() { alert(text); }
return sayAlert;
}
var say = sayHello('Bob');
say();
//}}}
注意sayAlert是sayHello的一个嵌套函数,当var say = sayHello('Bob')这行执行完之后,因为say是对内部函数sayAlert的一个引用,所以这个函数对象不会被释放,而sayAlert的执行环境(execution context)也不会被释放,一个函数与它的数据、执行环境绑在一起,这个sayHello就是一个闭包了。
这里有好几个概念: 嵌套函数,函数引用,作用域链(scope chain),执行环境。从目前看见的资料来看,闭包的构成必须有这几个要素。
* 作用
这个东西有什么作用呢,先看如下一个例子:
//{{{
var f, g;
function foo() {
var x = 0;
f = function() { return ++x; };
g = function() { return --x; };
x = 1;
print(f()); // "2"
}
foo();
print(g()); // "1"
print(f()); // "2"
//}}}
# 两个不同功能、相互独立的函数只能通过全局变量交换数据么(这里说语言本身提供的能力,而不是平台提供的能力)? 上面例子中两个函数都操作了变量x,但x并不是全局变量,但对于其他函数也是不可见的。可见第一个作用是提供另一种手段来供两段程序交换数据,同时保护变量安全
# 两个闭包建立之后,只需要根据两个引用就可以调用了,这两个引用相互独立,但又是完全自包含的,——这显然是函数式编程的风格了
* 链接
** [[Wikipedia: Closure|http://anonymouse.org/cgi-bin/anon-www.cgi/http://en.wikipedia.org/wiki/Closure_(computer_science)]]
** [[JavaScript Closures for Dummies|http://blog.morrisjohns.com/javascript_closures_for_dummies]], 中文翻译: [[在JavaScript中,什么是闭包|http://javascript.chinahtml.com/2006/javascript-11607091807203.shtml]])
** [[Javascript Closures|http://www.jibbering.com/faq/faq_notes/closures.html]],中文翻译: [[理解JavaScript Closure|http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html]]
** [[深入理解JavaScript闭包|http://www.felixwoo.com/article.asp?id=294]]
** [[JavaScript闭包讨论的相关例子|http://realazy.org/lab/js/closure.html]]
** [[对 "闭包-closure" 的一些见解|http://wj.cnblogs.com/archive/2006/04/22/381851.html]]
而Martin Fowler的解释却是[[另外一种|http://martinfowler.com/bliki/Closure.html]], 说闭包就是一段可作为参数传递的代码。从他提供的示例来看只是个匿名函数,跟嵌套函数没有什么关系,其他人也给出了[[C#|http://joe.truemesh.com/blog//000390.html]]、[[Python|http://ivan.truemesh.com/archives/000392.html]]和[[JavaScript|http://nonn-et-twk.net/twk/closure/]]上的例子,却跟上面的不一样。
//{{{
Array.prototype.select = function(func)
{
var ary = [];
for (var i = 0; i < this.length; ++i)
{
if (func(this[i]))
ary[ary.length] = this[i];
}
return ary;
};
function managers_noclosure(emps) {
var result = [];
for (var i = 0; i < emps.length; ++i)
{
var e = emps[i];
if (e.isManager) result[result.length] = e;
}
return result;
}
function managers(emps)
{
return emps.select(function (e){ return e.isManager; });
}
//}}}
而现在嚷嚷得比较厉害的Java支持也是依照这种概念的[[FIXME]]http://www.infoq.com/cn/news/2007/09/catching-up-with-closures
按照这种定义,闭包是非常类似于C语言中的函数指针、C++里面的模板函数、Java中的内嵌类,虽然Martin Fowler在他文章里也在说明闭包跟这些概念的不同时提到了运行环境的问题,但似乎没有什么说服力,至少从例子上是看不出来的。
个人感觉,前面一种说法是正确的,这种说法不大对。虽然Martin Fowler的名气很大。
|''Links''|Any {{{WikiWord}}} creates a link to a tiddler (whether it exists or not).<br />Note that a WikiWord has to start with a capital letter and have a further mix of upper and lower case.|[[WikiWord]]|
|~|Manual link<br />{{{[[Table of Contents]]}}} (Especially for tiddlers with spaces in their titles)|[[Table of Contents]]|
|~|{{{[[Pretty Link|Link]]}}}|[[Pretty Link|Link]]|
|~|Automatic external link {{{http://www.tiddlywiki.com}}}|http://www.tiddlywiki.com|
|~|Pretty external link<br />{{{[[My Home Page|http://www.tiddlywiki.com]]}}}|[[My Home Page|http://www.tiddlywiki.com]]|
|~|OS Folder link<br />Windows Share: {{{file://///server/share}}}<br />Windows Local: {{{file:///c:/folder/file}}}<br />Un*x Local File: {{{file://folder/file}}}<br />Relative File: {{{[[folder/file]]}}}|file://///server/share <br />file:///c:/folder/file <br />file://folder/file <br /> [[folder/file]]|
|''Images''|{{{[img[favicon.ico]]}}}<br />Note that image files are always external to the TW file|[img[http://www.tiddlywiki.com/favicon.ico]]|
|~|Right aligned<br />{{{[>img[favicon.ico]]}}}|[>img[http://www.tiddlywiki.com/favicon.ico]]|
|~|Left aligned<br />{{{[<img[favicon.ico]]}}}|[<img[http://www.tiddlywiki.com/favicon.ico]]|
|''Image Links''|{{{[img[fav.ico][TiddlerName]]}}}|[img[http://www.tiddlywiki.com/favicon.ico][TiddlerName]]|
|~|{{{[img[fav.ico][Alias|TiddlerName]]}}}|[img[http://www.tiddlywiki.com/favicon.ico][Alias|TiddlerName]]|
|~|{{{[img[fav.ico][http://www.aa.com]]}}}|[img[http://www.tiddlywiki.com/favicon.ico][http://www.tiddlywiki.com]]|
|~|>|also see ''Links'' and ''Images'' sections in this table|
|''Inline''<br />''Comments''|{{{Not shown: /% hidden comment %/}}}<br />Text between the markers will not be shown|Not shown:/% hidden text %/|
/***
|''Name:''|LoadExtPlugin|
|''Description:''|LoadExtPlugin allows you to load external extensions from the file lists (named .js) within those tiddlers taged with "ExtList".|
|''Version:''|1.8.0|
|''Date:''|Apr 30, 2007|
|''Source:''|http://www.sourceforge.net/projects/ptw/|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License]]|
|''CoreVersion:''|2.1.0|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0|
+++!^[Revision History:]
v1.8.0 (Apr 30 2007)
*config.macros.loadExt support to load singgle external script by using {{{<<loadExt '/pathto/scriptfile.js'>>}}}
*Ensure LoadExtPlugin loading itself and/or loadling scripts after core has been loaded with external core js and itself|
v1.7.2 (Sep 28 2006)
*Fixed bugs on IE
v1.7.1 (30 Aug 2006)
* Changed rule check of ExtList
v1.7.0 (20 Jul 2006)
* Runs compatibly with TW 2.1.0 (rev #403+)
v1.6.0 (13 Jul 2006)
* Fixed bugs in refreshCode and config.macros.loadExt.loadScripts on IE
* Runs compatibly with TW 2.1.0 (rev #359+)
v1.5.2 (21 Jun 2006)
* minor changes for XHTML compliant
v1.5.1 (26 Feb 2006)
* JSLint checked
v1.5.0 (02 Feb 2006)
* add new function config.macros.loadExt.LoadScripts(), keep all variables to be local, thanks Udo.
* Fixed several missing variable declarations
v1.4.0 (20 Jan 2006)
* refreshCode() improved.
v1.3.0 (14 Jan 2006)
* strip startup error massage for IE
v1.2.0 (13 Jan 2006)
* TiddlyWiki version 2.0.0 or above required.
* refreshCode() improved.
v1.1.0 (10 Jan 2006)
* To make the extensions list handling more robust, thanks Udo.
* Fix bugs for multi-tiddlers tagged with ExtList
v1.0.0 (07 Jan 2006)
* Combine the RefreshExt code and LoadExtPlugin, and also make TW 1.2 to be backward compatible, thanks Udo.
* Globle function refreshCode() added, and reserve the refreshExt macro.
* Fix a minor bug for variable "scriptfile".
v0.3.0 (29 Dec 2005)
* macro refreshExt modified to refresh formatter
v0.2.0 (24 Nov 2005)
* macro refreshExt modified for TW 1.2.39 beta 2 and above
v0.1.0 (25 Sep 2005)
* initial release
===
!''Code section:''
***/
//{{{
version.extensions.loadExt = {major: 1, minor: 8, revision: 0,
date: new Date("Apr 30, 2007"),
name: "LoadExtPlugin",
type: "Plugin",
author: "BramChen",
source: "http://sourceforge.net/project/showfiles.php?group_id=150646"
};
config.macros.loadExt = {};
config.macros.loadExt.handler = function(place,macroName,params){
if (params[0])
this.loadScriptFile(params[0]);
else
this.loadScripts();
};
config.macros.loadExt.loadScriptFile = function(scriptfile){
var scriptfile = scriptfile.trim();
if (scriptfile.length < 2 || scriptfile.substr(0,2) == "//" || scriptfile.indexOf(".js") == -1){
return;
}
// displayMessage("loaded: "+ scriptfile);
var n = document.createElement("script");
n.type = "text/javascript";
n.src = scriptfile;
document.getElementsByTagName("head")[0].appendChild(n);
};
config.macros.loadExt.loadScripts = function() {
var extTag = "ExtList";
var str = ""; var scripts = [];
var tiddlers = store.getTaggedTiddlers(extTag);
for(var s=0 ; s<tiddlers.length; s++){
str += store.getRecursiveTiddlerText(tiddlers[s].title)+"\n";
}
scripts = str.replace(/[;\r]/mg,"\n").split("\n");
for (var i=0; i<scripts.length-1; i++) {
this.loadScriptFile(scripts[i]);
}
if (config.browser.isIE){
// setTimeout(function(){window.refreshCode();return false;},500);
var lerInterval = setInterval(function(){if(formatter) {clearInterval(lerInterval); window.refreshCode();};},100);
}
else {
var theCodes = "//<![CDATA[\nwindow.refreshCode();//]]>";
n = document.createElement("script");
n.type = "text/javascript";
n.appendChild(document.createTextNode(theCodes));
document.getElementsByTagName("head")[0].appendChild(n);
this.refreshCodeInserted = true;
}
};
window.refreshCode = function (){
formatter = new Formatter(config.formatters);
story.forEachTiddler(function(title,e){story.refreshTiddler(title,DEFAULT_VIEW_TEMPLATE,true);});
refreshDisplay();
return false;
}
// setTimeout(function(){config.macros.loadExt.loadScripts();return false;},500);
loadextpluginInterval = setInterval(function(){
if(window.formatter) {
clearInterval(loadextpluginInterval);
if(!config.macros.loadExt.refreshCodeInserted)
config.macros.loadExt.loadScripts();
}
},100);
//}}}
/***
|''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);
}
//}}}
[[巴蛮子是谁|巴蛮子]]
[[TiddlyWiki的使用]]
''Gmail/Gtalk'': <html><a href="javascript:void open('mailto:bamanzi@'+'gmail.com')"><img border="0" alt="bamanzi AT gmail DOT com" src="http://gsig.brightdev.com/4/bamanzi.png"/></a></html>
''MSN'': bamanzi AT hotmail.com
''QQ'': 15704509
<<tagCloud>>
^^~TiddlyWiki 版本:<<version>>
© 2007 [[UnaMesa|http://www.unamesa.org/]]^^
/***
|Name|NestedSlidersPlugin|
|Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
|Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
|Version|2.3.4|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
This plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content.
!!!!!Documentation
>see [[NestedSlidersPluginInfo]]
!!!!!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
<<<
!!!!!Revisions
<<<
2008.01.08 - [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 - 2.3.4 added hijack for Animator.prototype.startAnimating(). Previously, the plugin code simply set the overflow to "visible" after animation. This code tweak corrects handling of elements that were styled with overflow=hidden/auto/scroll before animation by saving the overflow style and then restoring it after animation has completed.
|please see [[NestedSlidersPluginInfo]] for additional revision details|
2005.11.03 - 1.0.0 initial public release. Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
<<<
!!!!!Code
***/
//{{{
version.extensions.nestedSliders = {major: 2, minor: 3, revision: 4, date: new Date(2007,12,28)};
//}}}
//{{{
// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkDebugLazySliderDefer==undefined) config.options.chkDebugLazySliderDefer=false;
if (config.options.chkDebugLazySliderRender==undefined) config.options.chkDebugLazySliderRender=false;
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)
{
lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
{
// var defopen=lookaheadMatch[1]
// var cookiename=lookaheadMatch[2]
// var header=lookaheadMatch[3]
// var panelwidth=lookaheadMatch[4]
// var transient=lookaheadMatch[5]
// var class=lookaheadMatch[6]
// var label=lookaheadMatch[7]
// var openlabel=lookaheadMatch[8]
// var panelID=lookaheadMatch[9]
// var blockquote=lookaheadMatch[10]
// var deferred=lookaheadMatch[11]
// location for rendering button and panel
var place=w.output;
// default to closed, no cookie, no accesskey, no alternate text/tip
var show="none"; var cookie=""; var key="";
var closedtext=">"; var closedtip="";
var openedtext="<"; var openedtip="";
// extra "+", default to open
if (lookaheadMatch[1]) show="block";
// 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") }
show=config.options[cookie]?"block":"none";
}
// parse label/tooltip/accesskey: [label=X|tooltip]
if (lookaheadMatch[7]) {
var parts=lookaheadMatch[7].trim().slice(1,-1).split("|");
closedtext=parts.shift();
if (closedtext.substr(closedtext.length-2,1)=="=")
{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
openedtext=closedtext;
if (parts.length) closedtip=openedtip=parts.join("|");
else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
}
// parse alternate label/tooltip: [label|tooltip]
if (lookaheadMatch[8]) {
var parts=lookaheadMatch[8].trim().slice(1,-1).split("|");
openedtext=parts.shift();
if (parts.length) openedtip=parts.join("|");
else openedtip="hide "+openedtext;
}
var title=show=='block'?openedtext:closedtext;
var tooltip=show=='block'?openedtip:closedtip;
// create the button
if (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]);
btn.innerHTML=title; // enables use of HTML entities in label
// set extra button attributes
btn.setAttribute("closedtext",closedtext);
btn.setAttribute("closedtip",closedtip);
btn.setAttribute("openedtext",openedtext);
btn.setAttribute("openedtip",openedtip);
btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
btn.defOpen=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
}
btn.onmouseover=function(event) // mouseover on button aligns floater position with button
{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel); }
// create slider panel
var panelClass=lookaheadMatch[4]?"floatingPanel":"sliderPanel";
var panelID=lookaheadMatch[9]; if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
panel.button = btn; // so the slider panel know which button it belongs to
btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
panel.defaultPanelWidth=(lookaheadMatch[4] && lookaheadMatch[4].length>2)?lookaheadMatch[4].slice(1,-1):"";
panel.setAttribute("transient",lookaheadMatch[5]=="*"?"true":"false");
panel.style.display = show;
panel.style.width=panel.defaultPanelWidth;
panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }
// render slider (or defer until shown)
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
if ((show=="block")||!lookaheadMatch[11]) {
// render now if panel is supposed to be shown or NOT deferred rendering
w.subWikify(lookaheadMatch[10]?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
// align floater position with button
if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
}
else {
var src = w.source.substr(w.nextMatch);
var endpos=findMatchingDelimiter(src,"+++","===");
panel.setAttribute("raw",src.substr(0,endpos));
panel.setAttribute("blockquote",lookaheadMatch[10]?"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";
// toggle label
theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
// toggle tooltip
theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));
// deferred rendering (if needed)
if (theSlider.getAttribute("rendered")=="false") {
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 && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
else
theSlider.style.display = isOpen ? "none" : "block";
// reset to default width (might have been changed via plugin code)
theSlider.style.width=theSlider.defaultPanelWidth;
// align floater panel position with target button
if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);
// if showing panel, set focus to first 'focus-able' element in panel
if (theSlider.style.display!="none") {
var ctrls=theSlider.getElementsByTagName("*");
for (var c=0; c<ctrls.length; c++) {
var t=ctrls[c].tagName.toLowerCase();
if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
{ ctrls[c].focus(); break; }
}
}
var cookie=theTarget.sliderCookie;
if (cookie && cookie.length) {
config.options[cookie]=!isOpen;
if (config.options[cookie]!=theTarget.defOpen)
saveOptionCookie(cookie);
else { // remove cookie if slider is in default display state
var ex=new Date(); ex.setTime(ex.getTime()-1000);
document.cookie = cookie+"=novalue; path=/; expires="+ex.toGMTString();
}
}
// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
// but allow plain click to bubble up to page background (to dismiss open popup, if any)
if (e.shiftKey) { e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
return false;
}
//}}}
//{{{
// click in document background closes transient panels
document.nestedSliders_savedOnClick=document.onclick;
document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);
// call original click handler
if (document.nestedSliders_savedOnClick)
var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
// if click was inside transient panel (or something contained by a transient panel)... leave it alone
var p=target;
while (p)
if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
else p=p.parentNode;
if (p) return retval;
// otherwise, find and close all transient panels...
var all=document.all?document.all:document.getElementsByTagName("DIV");
for (var i=0; i<all.length; i++) {
// if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
// otherwise, if the panel is currently visible, close it by clicking it's button
if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button})
}
return retval;
};
//}}}
//{{{
// adjust floating panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
if (hasClass(panel,"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 && !hasClass(p,'floatingPanel')) p=p.parentNode;
if (p) { left-=findPosX(p); top-=findPosY(p); }
}
if (findPosX(btn)+panel.offsetWidth > getWindowWidth()) // adjust position to stay inside right window edge
left-=findPosX(btn)+panel.offsetWidth-getWindowWidth()+15; // add extra 15px 'fudge factor'
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
}
//}}}
//{{{
// 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 start/stop handlers so overflow style is saved and restored after animation has completed
if (version.major+.1*version.minor+.01*version.revision>=2.2) {
/**
Animator.prototype.core_startAnimating = Animator.prototype.startAnimating;
Animator.prototype.startAnimating = function() {
for(var t=0; t<arguments.length; t++)
arguments[t].element.save_overflow=arguments[t].element.style.overflow;
return this.core_startAnimating.apply(this,arguments);
};
**/
Morpher.prototype.coreStop = Morpher.prototype.stop;
Morpher.prototype.stop = function() {
this.coreStop.apply(this,arguments);
this.element.style.overflow = this.element.save_overflow||"visible";
};
}
//}}}
这些设置将缓存于浏览器
请签名<<option txtUserName>>
(范例:WikiWord)
<<option chkSaveBackups>> 保存备份
<<option chkAutoSave>> 自动保存
<<option chkRegExpSearch>> 正则式搜索
<<option chkCaseSensitiveSearch>> 区分大小写搜索
<<option chkAnimate>> 使用动画显示
<<themeSelect style 选择主题>>
----
[[进阶选项|AdvancedOptions]]
<!--{{{-->
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='content' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--}}}-->
|!Format|!Markup|!Example|
|''Headings''|{{{!!Heading 2}}}<br />{{{!!!Heading 3}}}<br />{{{!!!!Heading 4}}}<br />{{{!!!!!Heading 5}}}<br /><br />Usually avoid Heading1 as Tiddler titles are nominally Heading1.|<html><h2>Heading 2</h2><h3>Heading 3</h3><h4>Heading 4</h4><h5>Heading 5</h5></html>|
|''Lists''|{{{*Bulleted list}}}|<html><ul><li>Bulleted List</li></ul></html>|
|~|{{{#Numbered list}}}|<html><ol><li>Numbered List</li></ol></html>|
|~|Definition list<br />{{{;Term}}}<br />{{{:definition}}}|<html><dl><dt>Term</dt><dd>definition</dd></dl></html>|
|~|Lists can be mixed and nested<br />{{{*}}}Bullet<br />{{{*#}}}Number<br />{{{*#;}}}Item<br />{{{*#:}}}Definition|<html><ul><li>Bullet<ol><li>Numbered<dl><dt></dt>Item<dd>Definition</dd></dl></li></ol></li></ul></html>|
|''Block quotes''|{{{>Blockquote}}}<br />{{{>>Nested quote}}}|<html><blockquote>Blockquote<blockquote>Nested<br/> quote</blockquote></blockquote></html>|
|~|{{{<<<}}}<br />{{{multi-line}}}<br />{{{blockquote}}}<br />{{{<<<}}}|<html><blockquote>multi-line<br/>blockquote</blockquote></html>|
|''Horizontal Rule''|{{{----}}} (4 dashes on a line of their own)|<html><hr></html>|
maxNums: 10
includeTags: *
excludeTags: systemConfig,systemTiddlers,excludeLists,systemScript,tiddlyUsage
/***
!Metadata:
|''Name:''|RecentTiddlersPlugin|
|''Source:''|http://sourceforge.net/project/showfiles.php?group_id=150646|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''Version:''|1.1.1|
|''Date:''|Aug 28, 2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.1.0|
|''Description:''|Display DefaultTiddlers and recently modified tiddlers at startup.|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0; Opera|
!Usage:
>Just to set the options by changing the slice values in RecentTiddlersOptions, if needed.
!Revision History:
|''Version''|''Date''|''Note''|
|1.1.1|Aug 28, 2007|No more hijeck core restart()|
|1.1.0|Aug 25, 2007|Easy to change the options by using tiddler slices, defined in RecentTiddlersOptions|
|1.0.0|Apr 18, 2007|Initial release, codes reworked from Tim Morgan's RecentPlugin |
!Code section:
***/
//{{{
version.extensions.recentTiddlers = {major: 1, minor: 1, revision: 1, date: new Date("Aug 28, 2007")};
config.recentTiddlers = {
maxNums: 5,
includeTags: ['*'],
excludeTags: ['systemConfig','systemTiddlers', 'systemScript', 'excludeLists']
};
config.shadowTiddlers.RecentTiddlersOptions = 'maxNums: 5\nincludeTags: *\nexcludeTags: systemConfig,systemTiddlers,excludeLists';
config.recentTiddlers.getRecents = function (){
var c = store.getTiddlerSlices('RecentTiddlersOptions',['maxNums','includeTags','excludeTags']);
var maxNums = (c.maxNums) ? parseInt(c.maxNums) : config.recentTiddlers.maxNums;
var includeTags = (c.includeTags) ? c.includeTags.split(',') : config.recentTiddlers.includeTags;
var excludeTags = (c.excludeTags) ? c.excludeTags.split(',') : config.recentTiddlers.excludeTags;
var CPlingo = (config.CommentPlugin !== undefined)?config.CommentPlugin.CPlingo:null;
var rs = store.getTiddlerText("DefaultTiddlers").readBracketedList();
var tiddlers = store.getTiddlers("modified");
var n = tiddlers.length -1 - maxNums;
for (var t=tiddlers.length-1; t>n && t>0; t--){
if(CPlingo !== null && tiddlers[t].isTagged(CPlingo.comments)) {
var tt = tiddlers[t].title.split(CPlingo.CommentInTitle)[0];
if(store.tiddlerExists(tt))
rs.pushUnique(tt);
}
else {
if (tiddlers[t].tags.containsAny(excludeTags))
n--;
else {
if (includeTags.length == 0 || includeTags[0] == '*' || tiddlers[t].tags.containsAny(includeTags))
rs.pushUnique(tiddlers[t].title);
}
}
}
return rs;
};
if(!window.location.hash)
var recentInterval = setInterval(function(){if(story) {clearInterval(recentInterval); story.closeAllTiddlers();story.displayTiddlers(null,config.recentTiddlers.getRecents());};},100);
//}}}
/%
|Name|ReplaceDoubleClick|
|Source|http://www.TiddlyTools.com/#ReplaceDoubleClick|
|Version|2.0.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides|tiddler background click and doubleclick handlers|
|Description|disable doubleclick-to-edit-tiddler or replace doubleclick with shift/ctrl/alt+singleclick|
Usage:
in tiddler content:
<<tiddler ReplaceDoubleClick>> or
<<tiddler ReplaceDoubleClick with: key trigger>>
in ViewTemplate:
<span macro="tiddler ReplaceDoubleClick"></span> or
<span macro="tiddler ReplaceDoubleClick with: key trigger"></span>
where:
'key' (optional) is one of: none (default), ctrl, shift, or alt
'trigger' (optional) is one of: click, doubleclick (default)
* if no key parameter (or "none") is specified, then the double-click action is **disabled** for that tiddler.
* if a key (other than none) is specified, the doubleclick action for the tiddler will only be invoked
when the key+trigger combination is used.
* note: double-clicking will also trigger the single-click handler. As a result, when 'click' option is specified,
either click OR double-click (plus the specified key) will trigger the action.
Revisions:
2.0.0 renamed from ShiftClickToEdit and merged with DoubleClickDisable and added support specifying alternative key+click combination
%/<script>
var here=story.findContainingTiddler(place); if (!here) return;
if (here.ondblclick) {
here.setAttribute("editKey","none");
if ("$1"=="shift" || "$1"=="ctrl" || "$1"=="alt")
here.setAttribute("editKey","$1"+"Key");
var trigger=("$2"=="click")?"onclick":"ondblclick";
here.save_dblclick=here.ondblclick;
here.ondblclick=null;
if (here.getAttribute("editKey")!="none")
here[trigger]=function(e) {
var ev=e?e:window.event;
if (ev[this.getAttribute("editKey")])
this.save_dblclick.apply(this,arguments);
}
}
</script>
Goto: <<gotoTiddler>> <<collapseAll>><<expandAll>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY">><<saveChanges>><<tiddler TspotSidebar>> <<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
// //''Name:'' InsertSmiley
// //''Version:'' <<getversion smiley>> (<<getversiondate smiley "DD MMM YYYY">>)
// //''Author:'' AlanHecht
// //''Type:'' [[Macro|Macros]]
// //''Description:'' Inserts a small smiley graphic at the location of the macro and does not require any external graphics. The method used should work on most current browser platforms.
// //''Syntax:'' << {{{smiley ;-)}}}>>
// //Examples: <<smiley>> <<smiley :-(>> <<smiley ;-)>> <<smiley :-|>> <<smiley :-D>>
// //''Directions:'' <<tiddler MacroDirections>>
// //''Notes:'' A regular smiley <<smiley>> will be displayed if no smiley string is provided. Most smileys will work with or without the "nose" -- e.g. {{{;-)}}} is the same as {{{;)}}}
// //''Revision History:''
// // v0.1.0 (20 July 2005): initial release
// // v0.1.1 (20 July 2005): << {{{smiley}}}>> with no parameter displays a standard smiley
// //''Code section:''
version.extensions.smiley = {major: 0, minor: 1, revision: 1, date: new Date("Jul 20, 2005")};
config.macros.smiley = {}
config.macros.smiley.handler = function(place,macroName,params)
{
var palette = ["transparent","#000000","#1a1507","#352e18","#464646","#666666","#a3141e","#b06b63","#cc9900","#dd9030","#dddddd","#e89d00","#edc32a","#f3cb3c","#fdf201","#fdf526","#ff3149","#ffac00","#ffbf06","#ffc846","#ffcc66","#ffd758","#ffdd01","#ffea7b","#ffed55","#ffffff"];
var data = params;
var imageMap = null;
if(!data[0] || data[0] == ":-)" || data[0] == ":)")
imageMap = "aaaaabbbbbaaaaaaaabdtyyvtdbaaaaabnyxxxxxujbaaabmyyffyffuujbaadyyyeeyeetttdabppppddyddpmmlbbwoooooooowsrlbbwwpooooowwmrlbbwwboooowwwbllbbwwwboooowbrllbacwwwbbbbbrllcaablswwwwsrrlibaaablsssrrllibaaaaabcrrlllcbaaaaaaaabbbbbaaaaa";
else if(data[0] == ":-(" || data[0] == ":(")
imageMap = "aaaaabbbbbaaaaaaaabdtyyvtdbaaaaabnyxxxxxujbaaabmyyyyyyyuujbaadyyyeeyeetttdabppppddyddpmmlbbwoooooooowsrlbbwwpooooowwmrlbbwwoooooowwrllbbwwwwbbbbbsrllbacwwbwwwwsbllcaablswwwwsrrlibaaablsssrrllibaaaaabcrrlllcbaaaaaaaabbbbbaaaaa";
else if(data[0] == ";-)" || data[0] == ";)")
imageMap = "aaaaabbbbbaaaaaaaabdtyyvtdbaaaaabnyxxxxxujbaaabmyyxxxxxuujbaadyyyxxxeetttdabppphddyddpmmlbbwoooooooowsrlbbwwpooooowwmrlbbwwboooowwwbllbbwwwboooowbrllbacwwwbbbbbrllcaablswwwwsrrlibaaablsssrrllibaaaaabcrrlllcbaaaaaaaabbbbbaaaaa";
else if(data[0] == ":-|" || data[0] == ":|")
imageMap = "aaaaabbbbbaaaaaaaabdtyyvtdbaaaaabnyxxxxxujbaaabmyyffyffuujbaadyyyeeyeetttdabppppddyddpmmlbbwoooooooowsrlbbwwpooooowwmrlbbwwoooooowwrllbbwwwwbbbbbsrllbacwwwwwwwsrllcaablswwwwsrrlibaaablsssrrllibaaaaabcrrlllcbaaaaaaaabbbbbaaaaa";
else if(data[0] == ":-D" || data[0] == ":D")
imageMap = "aaaaabbbbbaaaaaaaabdtyyvtdbaaaaabnyxxxxxujbaaabmyyeeyeeuujbaadyyyeeyeetttdabppppyyyyypmmlbbwbbbbbbbbbbblbbwbkzzzzzzzkbwbbwbfzzzzzzzfbwbbwbkzzzzzzzkbwbacwbkzzzzzkblcaablsbkzzzkblibaaablsbbbbblibaaaaabcrrlllcbaaaaaaaabbbbbaaaaa";
else
createTiddlyElement(place,"span",null,"errorNoSuchMacro","unknown smiley");
if(imageMap)
{
var box = createTiddlyElement(place,"span",null,"smiley",String.fromCharCode(160));
box.style.position = "relative";
box.style.width = "15px";
box.style.height = "15px";
box.style.marginLeft = "1px";
box.style.marginRight = "1px";
box.style.paddingRight = "12px";
box.style.verticalAlign = "top";
//now divide into 15x15 grid and create each pixel
// rows
for(r=0; r<15; r++)
{
// columns
for(c=0; c<15; c++)
{
//create each pixel with the correct background
var pix = document.createElement("img");
pix.className = "smileyPixel";
pix.style.position = "absolute";
pix.border = 0;
pix.style.top = r + "px";
pix.style.left = c + "px";
pix.style.width = "1px";
pix.style.height = "1px";
pix.style.backgroundColor = palette[imageMap.charCodeAt((r*15)+c)-97];
pix.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
box.appendChild(pix);
}
}
}
}
|!Markup|!Explanation|
| {{{|}}} |Column Seperator |
| {{{!}}} |Heading (Row or Column) |
| {{{>}}} |Column Span |
| {{{~}}} |Row Span |
| {{{|Left |}}} |Left Align |
| {{{| Right|}}} |Right Align|
| {{{| Center |}}} |Center Align |
| {{{|Caption|c}}} |Table Caption (Can be at top or bottom)|
| {{{|Header|h}}} |Marks the row as being a header row (will be wrapped with a {{{<thead>}}} and so all entries are automatically formatted as per {{{|!}}} cells)|
| {{{|Footer|f}}} |Marks the row as being a footer row (will be wrapped with a {{{<tfoot>}}}, no special formatting is pre-defined for this but can be added to your own CSS)|
| {{{|CSSclass|k}}} |Applies a CSS class to the table to allow additional formatting (NB: only works if no whitespace after the k)|
|>|To have a table with no borders at all. Use {{{|noBorder|k}}} with the CSS (in your StyleSheet tiddler):<br />{{{ .noBorder,.noBorder td,.noBorder th,.noBorder tr{border:0} }}}|
|>|!Sample Table|
|>|{{{|table caption|c}}}<br />{{{|header|header|h}}}<br />{{{|text|more text|}}}<br />{{{|!heading|!heading|}}}<br />{{{|>|colspan|}}}<br />{{{|rowspan|left align |}}}<br />{{{|~| center |}}}<br />{{{|bgcolor(green):green| right|}}}<br />{{{|footer|footer|f}}} |
|>|<<tiddler ./tblShow>>|
!Notes
You can use the custom CSS formatter in combination with headers and lists to allow new lines within the entry. e.g.:
{{{
#{{block{
Bullet 1
Some text in the same bullet
(Note that "block" can be anything, it is the formatters CSS class name)
}}}
# Bullet 2
}}}
#{{block{
Bullet 1
Some text in the same bullet
}}}
# Bullet 2
(Julian Knight, 2006-05-11)
<part atEg hidden>
{{{
This is before the indented text
@@display:block;margin-left:2em;This text will be indented...
...and can even span across several lines...
...or even include blank lines.
@@This is after the indented text
}}}
This is before the indented text
@@display:block;margin-left:2em;This text will be indented...
...and can even span across several lines...
...or even include blank lines.
@@This is after the indented text
</part>
<part tblMarkup hidden>
{{{
|table caption|c
|header|header|h
|text|more text|
|!heading|!heading|
|>|colspan|
|rowspan|left align |
|~| center |
|bgcolor(green):green| right|
|footer|footer|f
}}}
</part>
<part tblShow hidden>
|table caption|c
|header|header|h
|text|more text|
|!heading|!heading|
|>|colspan|
|rowspan|left align |
|~| center |
|bgcolor(green):green| right|
|footer|footer|f
</part>
/***
|Name|TagCloudPlugin|
|Source|http://www.TiddlyTools.com/#TagCloudPlugin|
|Version|0.0.0|
|Author|Clint Checketts|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description||
!Usage
<<tagCloud>>
!Code
***/
//{{{
version.extensions.tagCloud = {major: 1, minor: 0 , revision: 0, date: new Date(2006,2,04)};
//Created by Clint Checketts, contributions by Jonny Leroy and Eric Shulman
config.macros.tagCloud = {
noTags: "No tag cloud created because there are no tags.",
tooltip: "%1 tiddlers tagged with '%0'"
};
config.shadowTiddlers.TagCloud="<<tagCloud>>";
config.macros.tagCloud.handler = function(place,macroName,params) {
var excludeTags = ['systemConfig', 'systemScript', 'systemTiddlers', 'excludeLists'];
var tagCloudWrapper = createTiddlyElement(place,"div",null,"tagCloud",null);
var tags = store.getTags();
for (var t=0; t<tags.length; t++) {
for (var p=0;p<params.length; p++) if (tags[t][0] == params[p]) tags[t][0] = "";
}
if(tags.length == 0)
createTiddlyElement(tagCloudWrapper,"span",null,null,this.noTags);
//Findout the maximum number of tags
var mostTags = 0;
for (var t=0; t<tags.length; t++) if (tags[t][0].length > 0){
if (tags[t][1] > mostTags) mostTags = tags[t][1];
}
//divide the mostTags into 4 segments for the 4 different tagCloud sizes
var tagSegment = mostTags / 4;
for (var t=0; t<tags.length; t++) if (tags[t][0].length > 0){
if (excludeTags.indexOf(tags[t][0])>=0) continue;
var tagCloudElement = createTiddlyElement(tagCloudWrapper,"span",null,null,null);
tagCloudWrapper.appendChild(document.createTextNode(" "));
var theTag = createTiddlyButton(tagCloudElement,tags[t][0],this.tooltip.format(tags[t]),onClickTag,"tagCloudtag tagCloud" + (Math.round(tags[t][1]/tagSegment)+1));
theTag.setAttribute("tag",tags[t][0]);
}
};
setStylesheet(".tagCloud span{height: 1.8em;margin: 3px;}.tagCloud1{font-size: 1.2em;}.tagCloud2{font-size: 1.4em;}.tagCloud3{font-size: 1.6em;}.tagCloud4{font-size: 1.8em;}.tagCloud5{font-size: 1.8em;font-weight: bold;}","tagCloudsStyles");
//}}}
|!Format|!Markup|!Example|
|Bold|{{{''Bold''}}} (2 single quotes)|''Bold''|
|Italic|{{{//Italic//}}}|//Italic//|
|Bold Italic|{{{''//Bold Italic//''}}}|''//Bold Italic//''|
|Underlined|{{{__Underline__}}}(2 underscores)|__Underlined__|
|Strikethough|{{{--Strikethrough--}}}<br />{{{--}}} replaced {{{==}}} for Stikethrough in TiddlyWiki 2.1|--Strikethrough--|
|Superscript|{{{Text^^Superscript^^}}}|Text^^Superscript^^|
|Subscript|{{{Text~~Subscript~~}}}|Text~~Subscript~~|
|Monospaced text|<html><code>{{{Monospaced}}}</code></html>|{{{Monospaced}}}|
|Monospaced multiline block|Put <html><code>{{{</code></html> and <html><code>}}}</code></html> on their own lines|<html><pre>{{{<br/>Monospaced<br/>Multi-line<br/>Block<br/>}}}</pre></html>|
|Highlight|{{{@@Highlight@@}}}|@@Highlight@@|
|Color|{{{@@color(green):green text@@}}}|@@color(green):green text@@ |
|~|{{{@@bgcolor(green):text@@}}}|@@bgcolor(green):text@@ |
|~|{{{@@bgcolor(#3399ff):text@@}}}|@@bgcolor(#3399ff):text@@|
|~|{{{@@bgcolor(#39f):text@@}}}|@@bgcolor(#39f):text@@|
|CSS Extended Highlights|{{{@@some css;Highlight@@}}}<br />For backwards compatibility, the following highlight syntax is also accepted:<br />{{{@@bgcolor(#ff0000):color(#ffffff):red coloured@@}}}|@@background-color:#ff0000;color:#ffffff;red coloured@@<br /><<slider AtEg ./atEg 'Extended example ...'>>|
|Custom CSS Class|<html><code>{{wrappingClass{Text that is now accentuated}}}</code></html><br />By default, the text is placed in a <span>. To use a <div> instead, insert a line break before the text (after the single {)<br />In the CSS:<br />{{{.wrappingClass {color: red;} }}}|Add .wrappingClass to StyleSheet|
|Any HTML|{{{<html><span>any</span><br />}}}<br />{{{<b>valid</b> <em>xhtml</em></html>}}}|<html><span>any</span><br /><b>valid</b> <em>xhtml</em></html>|
<<tidIDE id:example SystemInfo TiddlerTweaker +edit:GettingStarted>>
!!Plugins
!!!must-have
*GotoPlugin: view any tiddler by entering it's title - displays list of possible matches
*[[TiddlersBarPlugin|http://jackparke.googlepages.com/jtw.html]] A bar to switch between tiddlers through tabs (like browser tabs bar).
*[[FullScreenPlugin|http://twhelp.tiddlyspot.com/index.html]] Toggle between viewing tiddlers fullscreen and normally
> [[ToggleSideBarMacro |http://tw.lewcid.org/#ToggleSideBarMacro]] (requires InlineJavaScriptPlugin)
> ToggleLeftSideBar, ToggleRightSideBar,ToggleScrollingSideBar (requires InlineJavaScriptPlugin)
!!! Recommended
* NestedSliderPlugin: show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content
* SinglePageModePlugin + RearrangeTiddlersPlugin (shouldn't be used together with TiddlesBarPlugin)
* ReplaceDoubleClick (requires InlineJavaScriptPlugin)
!!! useful
!!!!for blogging
* [[RecentTiddlersPlugin|http://ptw.sf.net]]
* [[WeblogPlugin|http://tiddlystyles.com]]
* [[TagCloud|http://15black.bluedepot.com/twtests/tagcloud.htm]]
* TiddlerTweakerPlugin
* BreadcrumbsPlugin
* TableOfContentsPlugin
!!!!others
* [[FootnotesPlugin |http://tw.lewcid.org/]]
* [[FontSizePlugin|http://tw.lewcid.org/#FontSizePlugin]]
* [[BetterTimelineMacro|http://tw.lewcid.org/#BetterTimelineMacro]]
!!Authoring Plugins
* [[WikiBar|http://efms.emome.net/Web/Map/tiddlywiki/wikibar_demo_2.html]]
* TabEditPlugin (TiddlersBarPlugin addon?)
* [[LessBackupsPlugin|http://mptw.tiddlyspot.com/]]
* 如何支持中文
>方法一: 随便采用哪个模板,添加如下网址的内容为一个plugin
>http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hans/locale.zh-Hans.js
>
>方法二: 如果想将javascript代码与内容分离开来,可以采用[[ptw|http://ptw.sourceforge.net]]上的模板,它包含有TiddlyWiki.zh-Hans.js。还可以实现语言的动态切换。
*如何给模板指定备份目录
> 新建一个plugin(带systemConfig标签的tiddler),其内容为
>> config.options.txtBackupFolder = "twBackups";
<html>
这几日迷上了<a href="http://www.tiddlywiki.com/">TiddlyWiki</a>这个东西, 仅仅一个网页, 却将JavaScript,CSS和DOM的功能发挥到了极致。当年看见Gmail的时候惊叹网页上的东西也可以做得这样易用,而到了TiddlyWiki这里发现Gmail也不算啥了。
<p/>
简单地说,从名字上可以看出,它具有一些wiki的功能,但它自带条目(它管这叫做tiddler)的管理,点击名称时时显示内容到中间区域——其实这就是一个简单的笔记软件了,并且不用安装任何其他的软件,我以前都用<a href="http://notecase.sourceforge.net">notecase</a>来记录一些琐碎的东西,但现在用不着了。
<p/>
如果只是这样,还不算什么,但它还有宏、<a href="http://tiddlythemes.com">主题</a>、导入、导出等等功能。更强的是跟Firefox, Eclipse这样的东西类似,有一个很好的扩展机制,结果是有太多的插件使得我们可以把它做成一个GTD系统或者blog系统,<a href="http://www.socio-kybernetics.net/saurierduval/2005/07/tiddlywiki-mania.html">Blog before you Think</a>这篇文章就介绍了各种变体。
<p/>
唯一的限制在于这些编辑只能在本地文件上做,网页自身没有机制将内容提交到服务器上去。不过也有网站提供TiddlyWiki服务(<a href="http://www.tiddlyspot.com">http://www.tiddlyspot.com</a>),使得可以将服务保存到服务器,甚至下载到本地,修改完成后再点击网页上一个链接就上传了。<p/>
</html>
<<tagging tiddlyUsage>>
其他:
* Documentataion
** [[TWHelp|http://twhelp.tiddlyspot.com/index.html]]
** [[TiddlyWiki入门|http://www.tiddlywiki.cn/]]
*Misc
** [[zh_CN translations|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hans/locale.zh-Hans.js]]
** Firefox extension [[TiddlySnip|http://tiddlysnip.com]]
/***
Contains the stuff you need to use Tiddlyspot
Note you must also have UploadPlugin installed
***/
//{{{
// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'bamanzi';
// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
// disable autosave in d3
if (window.location.protocol != "file:")
config.options.chkGTDLazyAutoSave = false;
// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}
// create some shadow tiddler content
merge(config.shadowTiddlers,{
'WelcomeToTiddlyspot':[
"This document is a ~TiddlyWiki from tiddlyspot.com. A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //What now?// @@ Before you can save any changes, you need to enter your password in the form below. Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
"<<tiddler TspotControls>>",
"See also GettingStarted.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working online// @@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// @@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick. You can make changes and save them locally without being connected to the Internet. When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Help!// @@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]]. Also visit [[TiddlyWiki Guides|http://tiddlywikiguides.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help. If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
"",
"@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// @@ We hope you like using your tiddlyspot.com site. Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),
'TspotControls':[
"| tiddlyspot password:|<<option pasUploadPassword>>|",
"| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<<br>>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
"| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[announcements|http://announce.tiddlyspot.com/]], [[blog|http://tiddlyspot.com/blog/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),
'TspotSidebar':[
"<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . . " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),
'TspotOptions':[
"tiddlyspot password:",
"<<option pasUploadPassword>>",
""
].join("\n")
});
//}}}
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 03/03/2008 22:29:21 | bamanzi | [[/|http://bamanzi.tiddlyspot.com/]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
| 04/03/2008 00:01:08 | bamanzi | [[/|http://bamanzi.tiddlyspot.com/]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
| 04/03/2008 00:38:16 | bamanzi | [[/|http://bamanzi.tiddlyspot.com/]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
| 04/03/2008 01:21:39 | bamanzi | [[/|http://bamanzi.tiddlyspot.com/]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
| 04/03/2008 01:48:49 | bamanzi | [[/|http://bamanzi.tiddlyspot.com/]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
| 06/03/2008 23:18:33 | bamanzi | [[my-tiddlyspot.htm|file:///D:/My%20Documents/mywiki/my-tiddlyspot.htm]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . | ok |
| 18/03/2008 23:09:20 | bamanzi | [[my-tiddlyspot.htm|file:///D:/My%20Documents/mywiki/my-tiddlyspot.htm]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . | ok |
| 18/03/2008 23:34:59 | bamanzi | [[my-tiddlyspot.htm|file:///D:/My%20Documents/mywiki/my-tiddlyspot.htm]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . | ok |
| 27/03/2008 22:11:10 | bamanzi | [[my-tiddlyspot.htm|file:///D:/My%20Documents/mywiki/my-tiddlyspot.htm]] | [[store.cgi|http://bamanzi.tiddlyspot.com/store.cgi]] | . | [[index.html | http://bamanzi.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
major: 1, minor: 0, revision: 2,
date: new Date("Apr 19, 2007"),
source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
author: 'BidiX (BidiX (at) bidix (dot) info',
license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
coreVersion: '2.2.0 (Beta 5)'
};
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");
merge(config.macros.option.types, {
'pas': {
elementType: "input",
valueField: "value",
eventName: "onkeyup",
className: "pasOptionInput",
typeValue: config.macros.option.passwordInputType,
create: function(place,type,opt,className,desc) {
// password field
config.macros.option.genericCreate(place,'pas',opt,className,desc);
// checkbox linked with this password "save this password on this computer"
config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
// text savePasswordCheckboxLabel
place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
},
onChange: config.macros.option.genericOnChange
}
});
merge(config.optionHandlers['chk'], {
get: function(name) {
// is there an option linked with this chk ?
var opt = name.substr(3);
if (config.options[opt])
saveOptionCookie(opt);
return config.options[name] ? "true" : "false";
}
});
merge(config.optionHandlers, {
'pas': {
get: function(name) {
if (config.options["chk"+name]) {
return encodeCookie(config.options[name].toString());
} else {
return "";
}
},
set: function(name,value) {config.options[name] = decodeCookie(value);}
}
});
// need to reload options to load passwordOptions
loadOptionsCookie();
/*
if (!config.options['pasPassword'])
config.options['pasPassword'] = '';
merge(config.optionsDesc,{
pasPassword: "Test password"
});
*/
//}}}
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.0|
|''Date:''|May 5, 2007|
|''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 (#3125)|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
major: 4, minor: 1, revision: 0,
date: new Date("May 5, 2007"),
source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
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
//
// 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
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}
]);
},
refreshOptions: function(listWrapper) {
var uploadOpts = [
"txtUploadUserName",
"pasUploadPassword",
"txtUploadStoreUrl",
"txtUploadDir",
"txtUploadFilename",
"txtUploadBackupDir",
"chkUploadLog",
"txtUploadLogMaxLine",
]
var opts = [];
for(i=0; i<uploadOpts.length; i++) {
var opt = {};
opts.push()
opt.option = "";
n = uploadOpts[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 = 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,null,null,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 = Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
bidix.upload.httpUpload(rssUploadParams,convertUnicodeToUTF8(generateRss()),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 == httpStatus.NotFound)
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; 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');
/* don't want this for tiddlyspot sites
// Backstage
merge(config.tasks,{
uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");
*/
//}}}
<!--{{{-->
<span macro="tiddler ReplaceDoubleClick with: ctrl">
<div class='toolbar' macro='toolbar fullscreen closeTiddler closeOthers +editTiddler +write +easyEdit > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
* TiddlerBarPlugin
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed.
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<html><div xmlns="http://www.w3.org/1999/xhtml"> 在Planet Debian TW上看见的Jesse<a href="http://people.debian.org.tw/%7Ejesse/blog/2008/01/18/pidgin-231-2-with-msnp14-enabled-for-debian-sid-again/">提供了一个pidgin补丁版本(Debian sid)</a>, 其中MSN协议可以发送自定义表情图标了(原来只能接收),补丁来自<a href="http://developer.pidgin.im/ticket/1187">http://developer.pidgin.im/ticket/1187</a>。
向他询问了一下之后,我编译了一个win32版本:
<a target="_blank" href="http://bamanzi.inlsd.org/gnuwin32/pidgin-msn-send-emoticons-2.3.1-win32.tar.bz2">http://bamanzi.inlsd.org/gnuwin32/pi...-win32.tar.bz2</a>
需要先安装官方的2.3.1
先在主窗口"工具- Smiley"里面配置自定义表情,然后(目前好像得先重启pidgin)就可以在MSN的聊天窗口里使用这些表情了。
</div></html>
<html>
感谢<a href="http://www.donews.net/gradetwo">gradetwo</a>昨天<a href="http://www.linuxsir.org/bbs/thread320802.html">放出了</a>pidgin上飞信插件的源代码,俺今晚有空,编译了一个win32版本。
<a href="http://bamanzi.inlsd.org/gnuwin32/pidgin-fetion/pidgin-fetion-0.96-win32.tar.bz2">pidgin-fetion-0.96-win32.tar.bz2</a>
(可用于pidgin-2.3.1,解压后将libfetion.dll放到x:\Program Files\Pidgin\plugins\下,重启pidgin即可)
代码只需要做一点小修改: <a href="http://bamanzi.inlsd.org/gnuwin32/pidgin-fetion/fetion-0.96-win32.patch">fetion-0.96-win32.patch</a>
<p>
<img style="cursor: pointer; width: 320px;" src="http://bamanzi.inlsd.org/gnuwin32/pidgin-fetion/fetion-win32.gif" alt="" border="0" /></p><p style="font-weight: bold;">编译方法:</p><ol><li>先按pidgin网站的<a href="http://gaim.sourceforge.net/win32/build.php">win32版本编译 说明</a>编译pidgin. 注意以下几点:</li><ol><li>并不一定需要安装cygwin,cygwin安装起来比较麻烦。其实可以从<a href="http://sourceforge.net/projects/tcl/">tcl网站</a>下载一个msys + mingw就可以了;</li><li>主要<span style="font-family:monospace;">w32api</span>版本要在3.9以上。老版本在编译<span style="font-family:monospace;">pidgin\win32\gtkdocklet-win32.c</span>时会报告BITMAPV5HEADER没有定义;</li><li>如果没有安装<span style="font-family:monospace;">perl</span>和<span style="font-family:monospace;">tcl</span>,不一定要按网站上说的那样去下载安装,直接修改<span style="font-family:monospace;">libpurple\\plugins\Makefile.mingw</span>和<span style="font-family:monospace;">pidgin\plugins\Makefile.mingw</span>,注释掉相关行就行了</li></ol><li>在libpurple下解压fetion-0.96的源代码(即存在pidgin-2.3.1/libpurple/fetion目录)</li><li>打上补丁<a href="http://bamanzi.inlsd.org/gnuwin32/pidgin-fetion/fetion-0.96-win32.patch">fetion-0.96-win32.patch</a></li><li>执行<span style="font-family:monospace;">make -f Makefile.mingw</span>,编译得到libfetion.dll
</li></ol><p>
</html>
<html>
很多文章都讲到了将MFC程序迁移到wxWidgets上(首先要读的也许是IBM developerWorks上这篇 <a href="http://www.ibm.com/developerworks/cn/linux/guitoolkit/l-mfc/">将MFC应用程序移植到Linux</a>),但对于一个比较大的程序,要一下子完成移植也显得有些艰巨。所以我在琢磨有没有可能在一个程序中同时使用这两种技术(同时我看中了wxWidgets上使用wxPython时给应用程序带来的可扩展性,有兴趣的可以查看wxPython中的这个embed示例)。<p/>
wxWidgets的代码库中倒是有<a href="http://svn.wxwidgets.org/viewvc/wx/wxWidgets/trunk/samples/mfc/">一个wx和MFC混合的例子</a>(发布出来的2.6的代码包里面好像没有,2.8才有),它演示了如何在一个程序中分别有wx和MFC的窗口(分属于wxFrame和CFrameWnd类)。<p/>
但它没有解答的问题是:<span style="font-weight: bold;">怎样将一个wx的控件放到MFC上面去,或者反过来</span>。<p/>
在这个例子中,如果你想将wx的窗口作为应用程序开始时显示的窗口,就需要这个: <pre> m_pMainWnd = <b><span style="color: rgb(160, 32, 240);">new</span></b> CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());</pre> 如果你了解MFC对窗口的封装,就知道它基本没有自己的东西,CWnd这些类基本上没有自己的数据成员,基本上都是调用Windows API(只是把那些API中的HWND参数给省略了。所以任何一个Windows桌面上的窗口,要体现为一个CWnd类对象是很容易的,只需要调用CWnd::FromHwnd()或者CWnd::Attach()就可以了,示例中的CDummyWindow就是这样做的。基于这样的思路,我们很容易把其它的wx控件通过CDummyWindow放到MFC控件中去。<pre>
wxTreeCtrl * wxtree = new wxTreeCtrl(.....)
CDummyWindow *dummy = new CDummyWindow((HWND)wxtree->GetHWND());
dummy->SetParent(this);
</pre>
我们需要其实不要CDummyWindow也没有问题,只要这样:<pre>
wxTreeCtrl * wxtree = new wxTreeCtrl(....)
::SetParent(HWND)wxtree->GetHWND(), m_hWnd);</pre>
但这里有另外一个问题: <span style="font-family:Georgia,serif;"></span>创建一个wxWindow对象时是必须给出一个parent的,而这个parent又必须是wxWindow类型(除非为NULL)。<p/>
反过来要将MFC的东西放到wx上面就可以那么好运了,虽然也可以用上面这一招将MFC的控件显示出来,
但这些控件低于wx来说是透明的,你没法利用到wxSplitterWindow的分割功能,没法利用上各种layout manager/sizer。<p/>
在<a href="http://www.wxwidgets.org/wiki/index.php/WxWidgets_For_MFC_Programmers">wxWidgets For MFC Programmers</a>(from <a href="http://www.wxwidgets.org/wiki/">wxWidgets Wiki</a>)中讲述了如何将一个CWnd转换为wxWindow对象:<p/>
<pre>
wxWindow * win = new wxWindow();
win->SetHWND((WXHWND)hWnd);
win->AdoptAttributesFromHWND();
win->Reparent(wxGetApp().GetTopWindow());
</pre></html>
/***
|''Name:''|zh-HansTranslationPlugin|
|''Description:''|Translation of TiddlyWiki into Simply Chinese|
|''Source:''|http://tiddlywiki-zh.googlecode.com/svn/trunk/|
|''Subversion:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hans/locale.zh-Hans.js|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''Version:''|2.3.0|
|''Date:''|Jan 19, 2008|
|''Comments:''|Please make comments at http://groups-beta.google.com/group/TiddlyWiki-zh/|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
// --
// -- Translateable strings
// --
// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone
config.locale = 'zh-Hans'; // W3C language tag
if (config.options.txtUserName == 'YourName' || !config.options.txtUserName) // do not translate this line, but do translate the next line
merge(config.options,{txtUserName: "YourName"});
merge(config.tasks,{
save: {text: "保存", tooltip: "保存变更至此 TiddlyWiki", action: saveChanges},
sync: {text: "同步", tooltip: "将你的资料内容与外部服务器与文件同步", content: '<<sync>>'},
importTask: {text: "导入", tooltip: "自其他文件或服务器导入文章或插件", content: '<<importTiddlers>>'},
tweak: {text: "选项", tooltip: "改变此 TiddlyWiki 显示与行为设置", content: '<<options>>'},
plugins: {text: "插件管理", tooltip: "管理已安装的插件", content: '<<plugins>>'}
});
merge(config.optionsDesc,{
txtUserName: "编辑文章所使用之作者署名",
chkRegExpSearch: "启用正则式查找",
chkCaseSensitiveSearch: "查找时,区分大小写",
chkAnimate: "使用动画显示",
chkSaveBackups: "保存变更前,保留备份文件",
chkAutoSave: "自动保存变更",
chkGenerateAnRssFeed: "保存变更时,也保存 RSS feed",
chkSaveEmptyTemplate: "保存变更时,也保存空白模版",
chkOpenInNewWindow: "于新窗口开启链接",
chkToggleLinks: "点击已开启文章将其关闭",
chkHttpReadOnly: "非本机浏览文件时,隐藏编辑功能",
chkForceMinorUpdate: "修改文章时,不变更作者名称与日期时间",
chkConfirmDelete: "删除文章前须确认",
chkInsertTabs: "使用 tab 键插入定位字符,而非跳至下一个栏位",
txtBackupFolder: "存放备份文件的资料夹",
txtMaxEditRows: "编辑模式中显示列数",
txtFileSystemCharSet: "指定保存文件所在之档案系统之字符集 (仅适用于 Firefox/Mozilla only)"});
// Messages
merge(config.messages,{
customConfigError: "插件载入发生错误,详细请参考 PluginManager",
pluginError: "发生错误: %0",
pluginDisabled: "未执行,因标签设为 'systemConfigDisable'",
pluginForced: "已执行,因标签设为 'systemConfigForce'",
pluginVersionError: "未执行,插件需较新版本的 TiddlyWiki",
nothingSelected: "尚未作任何选择,至少需选择一项",
savedSnapshotError: "此 TiddlyWiki 未正确保存,详见 http://www.tiddlywiki.com/#DownloadSoftware",
subtitleUnknown: "(未知)",
undefinedTiddlerToolTip: "'%0' 尚无内容",
shadowedTiddlerToolTip: "'%0' 尚无内容, 但已定义隐藏的默认值",
tiddlerLinkTooltip: "%0 - %1, %2",
externalLinkTooltip: "外部链接至 %0",
noTags: "未设置标签的文章",
notFileUrlError: "须先将此 TiddlyWiki 存至本机文件,才可保存变更",
cantSaveError: "无法保存变更。可能的原因有:\n- 你的浏览器不支持此保存功能(Firefox, Internet Explorer, Safari and Opera 经适当设定后可保存变更)\n- 也可能是你的 TiddlyWiki 文件名称包含不合法的字符所致。\n- 或是 TiddlyWiki 文件被改名或搬移。",
invalidFileError: " '%0' 非有效之 TiddlyWiki 文件",
backupSaved: "已保存备份",
backupFailed: "无法保存备份",
rssSaved: "RSS feed 已保存",
rssFailed: "无法保存 RSS feed ",
emptySaved: "已保存模版",
emptyFailed: "无法保存模版",
mainSaved: "主要的TiddlyWiki已保存",
mainFailed: "无法保存主要 TiddlyWiki,所作的改变未保存",
macroError: "宏 <<\%0>> 执行错误",
macroErrorDetails: "执行宏 <<\%0>> 时,发生错误 :\n%1",
missingMacro: "无此宏",
overwriteWarning: "'%0' 已存在,[确定]覆盖之",
unsavedChangesWarning: "注意! 尚未保存变更\n\n[确定]保存,或[取消]放弃保存?",
confirmExit: "--------------------------------\n\nTiddlyWiki 以更改内容尚未保存,继续的话将丢失这些更动\n\n--------------------------------",
saveInstructions: "SaveChanges",
unsupportedTWFormat: "未支持此 TiddlyWiki 格式:'%0'",
tiddlerSaveError: "保存文章 '%0' 时,发生错误。",
tiddlerLoadError: "载入文章 '%0' 时,发生错误。",
wrongSaveFormat: "无法使用格式 '%0' 保存,请使用标准格式存放",
invalidFieldName: "无效的栏位名称:%0",
fieldCannotBeChanged: "无法变更栏位:'%0'",
loadingMissingTiddler: "正从服务器 '%1' 的:\n\n工作区 '%3' 中的 '%2' 撷取文章 '%0'"});
merge(config.messages.messageClose,{
text: "关闭",
tooltip: "关闭此讯息"});
config.messages.backstage = {
open: {text: "控制台", tooltip: "开启控制台执行编写工作"},
close: {text: "关闭", tooltip: "关闭控制台"},
prompt: "控制台:",
decal: {
edit: {text: "编辑", tooltip: "编辑 '%0'"}
}
};
config.messages.listView = {
tiddlerTooltip: "查看全文",
previewUnavailable: "(无法预览)"
};
config.messages.dates.months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
config.messages.dates.days = ["周日", "周一","周二", "周三", "周四", "周五", "周六"];
config.messages.dates.shortMonths = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
config.messages.dates.shortDays = ["日", "一","二", "三", "四", "五", "六"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
"th","th","th","th","th","th","th","th","th","th",
"st","nd","rd","th","th","th","th","th","th","th",
"st"];
config.messages.dates.am = "上午";
config.messages.dates.pm = "下午";
merge(config.messages.tiddlerPopup,{
});
merge(config.views.wikified.tag,{
labelNoTags: "未设标签",
labelTags: "标签: ",
openTag: "开启标签 '%0'",
tooltip: "显示标签为 '%0' 的文章",
openAllText: "开启以下所有文章",
openAllTooltip: "开启以下所有文章",
popupNone: "仅此文标签为 '%0'"});
merge(config.views.wikified,{
defaultText: "",
defaultModifier: "(未完成)",
shadowModifier: "(默认)",
dateFormat: "YYYY年0MM月0DD日",
createdPrompt: "创建于"});
merge(config.views.editor,{
tagPrompt: "设置标签之间以空白隔开,[[标签含空白时请使用双中括弧]],或点选现有之标签加入",
defaultText: ""});
merge(config.views.editor.tagChooser,{
text: "标签",
tooltip: "点选现有之标签加至本文章",
popupNone: "未设置标签",
tagTooltip: "加入标签 '%0'"});
merge(config.messages,{
sizeTemplates:
[
{unit: 1024*1024*1024, template: "%0\u00a0GB"},
{unit: 1024*1024, template: "%0\u00a0MB"},
{unit: 1024, template: "%0\u00a0KB"},
{unit: 1, template: "%0\u00a0B"}
]});
merge(config.macros.search,{
label: " 查找",
prompt: "搜索本 Wiki",
accessKey: "F",
successMsg: " %0 篇符合条件: %1",
failureMsg: " 无符合条件: %0"});
merge(config.macros.tagging,{
label: "引用标签:",
labelNotTag: "无引用标签",
tooltip: "列出标签为 '%0' 的文章"});
merge(config.macros.timeline,{
dateFormat: "YYYY年0MM月0DD日"});
merge(config.macros.allTags,{
tooltip: "显示文章- 标签为'%0'",
noTags: "没有标签"});
config.macros.list.all.prompt = "依字母排序";
config.macros.list.missing.prompt = "被引用且内容空白的文章";
config.macros.list.orphans.prompt = "未被引用的文章";
config.macros.list.shadowed.prompt = "这些隐藏的文章已定义默认内容";
config.macros.list.touched.prompt = "自下载或添加后被修改过的文章";
merge(config.macros.closeAll,{
label: "全部关闭",
prompt: "关闭所有开启中的 tiddler (编辑中除外)"});
merge(config.macros.permaview,{
label: "永久链接",
prompt: "可存取现有开启之文章的链接位址"});
merge(config.macros.saveChanges,{
label: "保存变更",
prompt: "保存所有文章,生成新的版本",
accessKey: "S"});
merge(config.macros.newTiddler,{
label: "创建文章",
prompt: "创建 tiddler",
title: "创建文章",
accessKey: "N"});
merge(config.macros.newJournal,{
label: "创建日志",
prompt: "创建 jounal",
accessKey: "J"});
merge(config.macros.options,{
wizardTitle: "增订的进阶选项",
step1Title: "增订的选项保存于浏览器的 cookies",
step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>显示未知选项</input>",
unknownDescription: "//(未知)//",
listViewTemplate: {
columns: [
{name: 'Option', field: 'option', title: "选项", type: 'String'},
{name: 'Description', field: 'description', title: "说明", type: 'WikiText'},
{name: 'Name', field: 'name', title: "名称", type: 'String'}
],
rowClasses: [
{className: 'lowlight', field: 'lowlight'}
]}
});
merge(config.macros.plugins,{
wizardTitle: "插件管理",
step1Title: "- 已载入之插件",
step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
skippedText: "(此插件因刚加入,故尚未执行)",
noPluginText: "未安装插件",
confirmDeleteText: "确认是否删除此文章:\n\n%0",
removeLabel: "删除 'systemConfig' 标签",
removePrompt: "删除 'systemConfig' 标签",
deleteLabel: "删除",
deletePrompt: "永远删除所选插件",
listViewTemplate : {
columns: [
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
{name: 'Tiddler', field: 'tiddler', title: "插件", type: 'Tiddler'},
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
{name: 'Forced', field: 'forced', title: "强制执行", tag: 'systemConfigDisable', type: 'TagCheckbox'},
{name: 'Disabled', field: 'disabled', title: "停用", tag: 'systemConfigDisable', type: 'TagCheckbox'},
{name: 'Executed', field: 'executed', title: "已载入", type: 'Boolean', trueText: "是", falseText: "否"},
{name: 'Startup Time', field: 'startupTime', title: "载入时间", type: 'String'},
{name: 'Error', field: 'error', title: "载入状态", type: 'Boolean', trueText: "错误", falseText: "正常"},
{name: 'Log', field: 'log', title: "记录", type: 'StringList'}
],
rowClasses: [
{className: 'error', field: 'error'},
{className: 'warning', field: 'warning'}
]}
});
merge(config.macros.toolbar,{
moreLabel: "其他",
morePrompt: "显示更多工具命令"
});
merge(config.macros.refreshDisplay,{
label: "刷新",
prompt: "刷新此 TiddlyWiki 显示"
});
merge(config.macros.importTiddlers,{
readOnlyWarning: "TiddlyWiki 于唯读模式下,不支持导入文章。请由本机(file://)开启 TiddlyWiki 文件",
wizardTitle: "自其他档案或服务器汇入文章",
step1Title: "步骤一:指定服务器或来源文件",
step1Html: "指定服务器类型:<select name='selTypes'><option value=''>选取...</option></select><br>请输入网址或路径:<input type='text' size=50 name='txtPath'><br>...或选择来源文件:<input type='file' size=50 name='txtBrowse'><br><hr>...或选择指定的馈入来源:<select name='selFeeds'><option value=''>选取...</option></select>",
openLabel: "开启",
openPrompt: "开启文件或",
openError: "读取来源文件时发生错误",
statusOpenHost: "正与服务器建立连线",
statusGetWorkspaceList: "正在取得可用之文章清单",
step2Title: "步骤二:选择工作区",
step2Html: "输入工作区名称:<input type='text' size=50 name='txtWorkspace'><br>...或选择工作区:<select name='selWorkspace'><option value=''>选取...</option></select>",
cancelLabel: "取消",
cancelPrompt: "取消本次导入动作",
statusOpenWorkspace: "正在开启工作区",
statusGetTiddlerList: "正在取得可用之文章清单",
step3Title: "步骤三:选择欲导入之文章",
step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>保持这些文章与服务器链接,便于同步后续的变更。</input><br><input type='checkbox' name='chkSave'>保存此服务器的详细资讯于标签为 'systemServer' 的文章名为:</input> <input type='text' size=25 name='txtSaveTiddler'>",
importLabel: "导入",
importPrompt: "导入所选文章",
confirmOverwriteText: "确定要覆写这些文章:\n\n%0",
step4Title: "步骤四:正在导入%0 篇文章",
step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
doneLabel: "完成",
donePrompt: "关闭",
statusDoingImport: "正在导入文章 ...",
statusDoneImport: "所选文章已导入",
systemServerNamePattern: "%2 位于 %1",
systemServerNamePatternNoWorkspace: "%1",
confirmOverwriteSaveTiddler: "此 tiddler '%0' 已经存在。点击“确定”以服务器上料覆写之,或“取消”不变更后离开",
serverSaveTemplate: "|''Type:''|%0|\n|''网址:''|%1|\n|''工作区:''|%2|\n\n此文为自动产生纪录服务器之相关资讯。",
serverSaveModifier: "(系统)",
listViewTemplate: {
columns: [
{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
{name: 'Tags', field: 'tags', title: "标签", type: 'Tags'}
],
rowClasses: [
]}
});
merge(config.macros.sync,{
listViewTemplate: {
columns: [
{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
{name: 'Server Type', field: 'serverType', title: "服务器类型", type: 'String'},
{name: 'Server Host', field: 'serverHost', title: "服务器主机", type: 'String'},
{name: 'Server Workspace', field: 'serverWorkspace', title: "服务器工作区", type: 'String'},
{name: 'Status', field: 'status', title: "同步情形", type: 'String'},
{name: 'Server URL', field: 'serverUrl', title: "服务器网址", text: "View", type: 'Link'}
],
rowClasses: [
],
buttons: [
{caption: "同步更新这些文章", name: 'sync'}
]},
wizardTitle: "将你的资料内容与外部服务器与文件同步",
step1Title: "选择欲同步的文章",
step1Html: '<input type="hidden" name="markList"></input>',
syncLabel: "同步",
syncPrompt: "同步更新这些文章",
hasChanged: "已更动",
hasNotChanged: "未更动",
syncStatusList: {
none: {text: "...", color: 'transparent'},
changedServer: {text: "服务器资料已更动", color: '#80ff80'},
changedLocally: {text: "本机资料已更动", color: '#80ff80'},
changedBoth: {text: "已同时更新本机与服务器上的资料", color: '#ff8080'},
notFound: {text: "服务器无此资料", color: 'ffff80'},
putToServer: {text: "已储存更新资料至服务器", color: '#ff80ff'},
gotFromServer: {text: "已从服务器撷取更新资料", color: '#80ffff'}
}
});
merge(config.macros.annotations,{
});
merge(config.commands.closeTiddler,{
text: "关闭",
tooltip: "关闭本文"});
merge(config.commands.closeOthers,{
text: "关闭其他",
tooltip: "关闭其他文章"});
merge(config.commands.editTiddler,{
text: "编辑",
tooltip: "编辑本文",
readOnlyText: "查阅",
readOnlyTooltip: "查阅本文之原始内容"});
merge(config.commands.saveTiddler,{
text: "完成",
tooltip: "确定修改"});
merge(config.commands.cancelTiddler,{
text: "取消",
tooltip: "取消修改",
warning: "确定取消对 '%0' 的修改吗?",
readOnlyText: "完成",
readOnlyTooltip: "返回正常显示模式"});
merge(config.commands.deleteTiddler,{
text: "删除",
tooltip: "删除文章",
warning: "确定删除 '%0'?"});
merge(config.commands.permalink,{
text: "永久链接",
tooltip: "本文永久链接"});
merge(config.commands.references,{
text: "引用",
tooltip: "引用本文的文章",
popupNone: "本文未被引用"});
merge(config.commands.jump,{
text: "跳转",
tooltip: "跳转至其他已开启的文章"});
merge(config.commands.syncing,{
text: "同步",
tooltip: "本文章与服务器或其他外部文件的同步资讯",
currentlySyncing: "<div>同步类型:<span class='popupHighlight'>'%0'</span></"+"div><div>与服务器:<span class='popupHighlight'>%1 同步</span></"+"div><div>工作区:<span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
notCurrentlySyncing: "无进行中的同步动作",
captionUnSync: "停止同步此文章",
chooseServer: "与其他服务器同步此文章:",
currServerMarker: "\u25cf ",
notCurrServerMarker: " "});
merge(config.commands.fields,{
text: "栏位",
tooltip: "显示此文章的扩充资讯",
emptyText: "此文章没有扩充栏位",
listViewTemplate: {
columns: [
{name: 'Field', field: 'field', title: "扩充栏位", type: 'String'},
{name: 'Value', field: 'value', title: "内容", type: 'String'}
],
rowClasses: [
],
buttons: [
]}});
merge(config.shadowTiddlers,{
DefaultTiddlers: "GettingStarted",
GettingStarted: "使用此 TiddlyWiki 的空白模版之前,请先修改以下默认文章:\n* SiteTitle 及 SiteSubtitle:网站的标题和副标题,显示于页面上方<br />(在保存变更后,将显示于浏览器视窗的标题列)。\n* MainMenu:主菜单(通常在页面左侧)。\n* DefaultTiddlers:包含一些文章的标题,可于进入TiddlyWiki 后开启。\n请输入您的大名,作为所创建/ 编辑文章的署名:<<option txtUserName>>",
MainMenu: "[[使用说明|GettingStarted]]\n\n\n^^~TiddlyWiki 版本:<<version>>\n© 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
OptionsPanel: "这些设置将缓存于浏览器\n请签名<<option txtUserName>>\n(范例:WikiWord)\n\n<<option chkSaveBackups>> 保存备份\n<<option chkAutoSave>> 自动保存\n<<option chkRegExpSearch>> 正则式搜索\n<<option chkCaseSensitiveSearch>> 区分大小写搜索\n<<option chkAnimate>> 使用动画显示\n----\n[[进阶选项|AdvancedOptions]]",
SiteTitle: "我的 TiddlyWiki",
SiteSubtitle: "一个可重复使用的个人网页式笔记本",
SiteUrl: 'http://www.tiddlywiki.com/',
SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal " YYYY年0MM月0DD日" "日志">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "偏好设置 »" "变更 TiddlyWiki 选项">>',
SideBarTabs: '<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "全部" "所有文章" TabAll "分类" "所有标签" TabTags "更多" "其他" TabMore>>',
StyleSheet: '[[StyleSheetLocale]]',
TabMore: '<<tabs txtMoreTab "未完成" "内容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "默认文章" "默认的影子文章" TabMoreShadowed>>'});
merge(config.annotations,{
AdvancedOptions: "此默认文章可以存取一些进阶选项。",
ColorPalette: "此默认文章里的设定值,将决定 ~TiddlyWiki 使用者介面的配色。",
DefaultTiddlers: "当 ~TiddlyWiki 在浏览器中开启时,此默认文章里列出的文章,将被自动显示。",
EditTemplate: "此默认文章里的 HTML template 将决定文章进入编辑模式时的显示版面。",
GettingStarted: "此默认文章提供基本的使用说明。",
ImportTiddlers: "此默认文章提供存取导入中的文章。",
MainMenu: "此默认文章的内容,为于屏幕左侧主菜单的内容",
MarkupPreHead: "此文章的内容将加至 TiddlyWiki 文件的 <head> 段落的起始",
MarkupPostHead: "此文章的内容将加至 TiddlyWiki 文件的 <head> 段落的最后",
MarkupPreBody: "此文章的内容将加至 TiddlyWiki 文件的 <body> 段落的起始",
MarkupPostBody: "此文章的内容将加至 TiddlyWiki 文件的 <body> 段落的最后,于 script 区块之前",
OptionsPanel: "此默认文章的内容,为于屏幕右侧副菜单中的选项面板里的内容",
PageTemplate: "此默认文章里的 HTML template 决定的 ~TiddlyWiki 主要的版面配置",
PluginManager: "此默认文章提供存取插件管理员",
SideBarOptions: "此默认文章的内容,为于屏幕右侧副菜单中选项面板里的内容",
SideBarTabs: "此默认文章的内容,为于屏幕右侧副菜单中的页签面板里的内容",
SiteSubtitle: "此默认文章的内容为页面的副标题",
SiteTitle: "此默认文章的内容为页面的主标题",
SiteUrl: "此默认文章的内容须设定为文件发布时的完整网址",
StyleSheetColors: "此默认文章内含的 CSS 规则,为相关的页面元素的配色。''勿修改此文'',請於 StyleSheet 中作增修。",
StyleSheet: "此默认文章内容可包含 CSS 规则",
StyleSheetLayout: "此默认文章内含的 CSS 规则,为相关的页面元素的版面配置。''勿修改此文'',請於 StyleSheet 中作增修。",
StyleSheetLocale: "此默认文章内含的 CSS 规则,可依翻译语系做适当调整",
StyleSheetPrint: "此默认文章内含的 CSS 规则,用于列印时的样式",
TabAll: "此默认文章的内容,为于屏幕右侧的“全部”页签的内容",
TabMore: "此默认文章的内容,为于屏幕右侧的“更多”页签的内容",
TabMoreMissing: "此默认文章的内容,为于屏幕右侧的“未完成”页签的内容",
TabMoreOrphans: "此默认文章的内容,为于屏幕右侧的“未引用”页签的内容",
TabMoreShadowed: "此默认文章的内容,为于屏幕右侧的“默认文章”页签的内容",
TabTags: "此默认文章的内容,为于屏幕右侧的“分类”页签的内容",
TabTimeline: "此默认文章的内容,为于屏幕右侧的“最近更新”页签的内容",
ViewTemplate: "此默认文章里的 HTML template 决定文章显示的样子"
});
//}}}
<html>在box.net上申请了一个账号,将《X档案》和《老友记》剧本CHM传了上去。<p/>
<a href="http://public.box.net/bamanzi">http://public.box.net/bamanzi</a><p/>
这个账号本来是为了上传<a href="http://amb.vis.ne.jp/mozilla/scrapbook/">ScrapBook</a>中保存的文摘才申请的——我在ScrapBook的网站上看见了<a href="http://amb.vis.ne.jp/mozilla/scrapbook/addons.php?lang=en">ScrapBox.net</a>这个扩展的扩展。<p/>
网页速度有点慢,但上传、下载还不是太差。<p/>
以后一些非技术的东西或者体积比较大点的东西就传到这里吧。技术方面的东西还是在 <a href="http://bamanzi.inlsd.org/">http://bamanzi.inlsd.org </a>上</html>
另请参见上次[[采用TiddlyWiki搭建blog]]。
几个插件仓库:
* [[TiddlyValut|http://tiddlyvault.tiddlyspot.com]]: 插件分类列表
* [[TiddlyTools|http://www.tiddlytools.com]]: 带有95个插件,大都在该页面内有实际应用,效果很炫
* [[TiddlyWikiPlugin|http://del.icio.us/TiddlyWikiPlugin]]: 插件开发社区大都在del.icio.us上登记插件
编辑器
* [[TidIDE Editor|http://www.tiddlytools.com/#TidIDEPlugin]]: TidIDE包中一个集成的编辑器,可以直接选择帖子编辑
* [[EasyEdit|http://visualtw.ouvaton.org/VisualTW.html]], a lite and fully integrated solution.
* [[FCKEditor|http://visualtw.ouvaton.org/VisualTW.html]], a more powerful solution, but requires an external component (FCKeditor).
* [[Externalize|http://visualtw.ouvaton.org/VisualTW.html]], to edit tiddlers in your favorite application like html editor, text or word processor, javascript IDE, css editor, ... It requires Firefox and it's All Text! extension.
* [[DelciousTagging|http://jackparke.googlepages.com/jtw.html]] Allows easy 'del.icio.us'-like tagging in the EditTemplate by showing all tags as a list of link-buttons.
* [[TabEditPlugin|http://tw.lewcid.org/#TabEditPlugin]] Easier tab editing - double click to edit source tiddler
页面效果:
* [[RearrangeTiddlersPlugin|http://www.tiddlytools.com/#RearrangeTiddlersPlugin]]: 可以拖到帖子(tiddler)标题来调节多个帖子的顺序(不过视觉效果不咋样,远不如iGoogle)
* [[TiddersBarPlugin|http://visualtw.ouvaton.org/VisualTW.html]] 以标签页的方式(就是Firefox那种标签页)显示多个帖子
* [[SinglePageModePlugin|http://www.tiddlytools.com/#SinglePageModePlugin]] 打开帖子时,其他帖子会自动关闭
帖子内容
* [[NestedSlidersPlugin|http://www.tiddlytools.com/#NestedSlidersPlugin]]
* [[Syntaxify|http://bob.mcelrath.org/syntaxify.html]] 如果你常在帖子中贴代码, 这个语法高亮插件应该用得着。不是“格式化”,而是加入此插件后帖子中的代码会直接高亮。缺省支持CSS,JavaScript和XML,其它可自己扩充;
* [[FootnotesPlugin|http://tw.lewcid.org/#FootnotesPlugin]] Create automated tiddler footnotes.
* [[TiddlerNotesPlugin|http://tw.lewcid.org/#TiddlerNotesPlugin]] Add notes to tiddlers without modifying the original content
其它
* [[LessBackupPlugin|http://mptw.tiddlyspot.com/]] 想让TiddlyWiki少几个备份文件
* [[ArchiveTimeline|http://ptw.sourceforge.net/]] 修改右边的"最近更新"列表,改为按照每月一个分类,适合于blog系统或者记事
<html>
节前在<a href="http://debaday.debian.net/">Debian Package of the Day</a>上看到<a href="http://debaday.debian.net/2007/11/11/debfoster-remove-a-package-and-its-dependencies/">debfoster的介绍</a>,说是比<a href="http://packages.debian.org/deborphan">deborphan</a>可以更进一步清理系统不必要的包,就拉下来玩玩,没想到用它删了一些包之后,使用GNOME时系统老是僵死,除了鼠标箭头,其它啥反应没有(包括Ctl-Alt-Backspace),只能按电源键。
折腾了几日不见起色,干脆就apt-get dist-upgrade再apt-get upgrade了,反正有近半年没做大面积更新了。这次下载了1000多个包,530多M,可折腾了些时间。
结果如下:
<ul><li>当然,系统不死机了;
</li><li>GNOME升级到了2.20,没留意到什么大的变化,倒是首选项精简了许多。另外<a href="http://dev.inlsd.org/projects/lunar-applet">lunar-applet</a>不能用了,回头重新编译一下试试;</li><li>totem-gstreamer和totem-xine现在可以同时安装了,依靠Debian alternatives连接到/usr/bin/totem (不过我还是不知道gstreamer版本有什么优点,它好像很多格式都不支持)
</li><li>一直在用的小企鹅(fcitx)不好使了,输入条开始可看到,但一开始敲字符就死了。只得切换到scim去;</li><li>装了个以前在cygwin下试玩过的<a href="http://tilda.sourceforge.net/">tilda</a>,感觉用热键呼出比切换到Gnome Terminal方便
</li><li>顺便从<a href="http://www.debian-multimedia.org/">Debian multimedia</a> (镜像: <a href="http://update.inlsd.org/debian-multimedia/">http://update.inlsd.org/debian-multimedia/</a> ) 升级了flash-player(<a href="http://www.debian-multimedia.org/flashplayer/">可从这里手工下载安装</a>)。现在可以全屏了,爽。但设置界面还是乱码</li><li>pidgin升级到了2.3.1,没见到明显的改进,反而QQ群功能出现问题:名字都显示成"(NULL)",而且几个"(NULL)"群也区分不开</li></ul>总而言之,不太爽,不过系统死机的问题倒是解决了。</html>
<html>
这几天发现了多媒体和即时通讯(这两类也算网民们用电脑最普遍的用途吧)方面的几个新玩意:<p/>
</dt><dt><a href="http://gmlive.googlecode.com/">网络电视GMLive</a> (<a href="http://photo14.yupoo.com/20080103/204516_1006507012_ypuujqjf.jpg">图</a>,<a href="http://cyclone.blog.ubuntu.org.cn/">开发团队blog</a>,<a href="http://cyclone.blog.ubuntu.org.cn/2007/12/13/gmlive-011-release/">使用说明</a>)</dt><dd>目前支持MMS, sopcast, nslive等几种流媒体,UI还比较简单</dd><dt>
</dt><dt>网络视频nslive (<a href="http://linuxtoy.org/archives/nslive.html">LinuxToy上的介绍</a>,<a href="http://linuxtoy.org/img/2007/11/nslive-thumb.png">图</a>, <a href="http://andycl98.blog.163.com/">作者的Blog</a>, <a href="http://www.newseetv.com/install.html">安装方法说明</a>)</dt><dd>上面提到过的一种流媒体。支持可用性上做的不太好,那个安装说明也够难找的。</dd><dt>
</dt><dt><a href="http://labs.adobe.com/technologies/flashplayer9/">Flash Player 9.0</a> (<a href="http://www.debian-multimedia.org/pool/main/f/flash-player/">Debian包</a>)</dt><dd>新版本支持Linux下的全屏了(并且支持硬件缩放hardware scaling)</dd><dt>
</dt><dt><a href="http://audacious-media-player.org/">Audacious</a> </dt><dd>喜欢Winamp/XMMS的可以用这个了( XMMS -> BMP -> Audacious,功能界面都差不多,都可以用winamp的skin;BMPx和<a href="http://wiki.xmms2.xmms.se/">XMMS2</a>却是另外一条路了)。至于功能方面,id3 tag的乱码还是避免不了的,除非自己改代码;另外我现在看重网络音频的支持了(比如电台或者<a href="http://last.fm/">last.fm</a>),很多时候懒得自己去下载mp3文件。</dd></dl><dl><dt><a href="http://www.linuxsir.org/bbs/thread320802.html">飞信的pigdin插件</a> (可以放到$HOME/.purple/plugins/或者/usr/lib/purple-2)</dt><dd>当然是第三方开发的。目前有基本功能:对聊或者发短信。最近几天作者<a href="http://www.donews.net/gradetwo">gradetwo</a>改 进很频繁,代码还没有放出来。我已经迫不及待要编译win32版本了:在Windows上时如果MSN、QQ、Google Talk、飞信、V网伴侣这些都打开,机器都没法玩了。也不知道现在这些软件怎么搞的,为了界面漂亮一点点,都要拼图片来做,搞得这些软件好用内存相当严 重。还是用pidgin一统天下好。</dd><dt>
</dt><dt><a href="http://code.google.com/p/musictracker/">MusicTracker</a> </dt><dd><i>A Pidgin 'now playing' plugin to advertise the songs you are listening to in your status message.</i></dd></dl><dl><dt>MSN客户端<a href="http://www.kmess.org/">KMess</a>发布<a href="http://www.kmess.org/news/">1.5正式版本</a></dt><dd>经过两个pre版本后,KMess终于发布了1.5正式版本,主要解决了文件传输过慢问题,新增了对用户自定义表情图片(emoticons)的发送支持。</dd></dl>
</html>
字符集和编码一直很头疼的一块,最近为了搞培训,研究了一下,发现以前确实有很多不明白甚至是错误的认识:
* ISO-8859-1 .. ISO-8859-16 这些都是西欧各国用的字符集,主要的差别在与128-255之间各自代表的字符不同;
* 仍然不明白为啥GB2312, Big5这些就算MBCS,而同样采用多字节编码的Unicode却不算
* GBK应该是GB2312的超集,向下兼容GB2312的,记得以前谁跟我说不是,我迷惑了好一阵;
* 很多编辑器说可以支持"Unicode编码",并且一些软件说"Unicode"就是两字节编码,这都是基于Unicode 4.0之前的认识。在那之前,Unicode跟GB2312这样的名称一样,即是字符集(charset)名称又是编码(encoding)名称, Unicode字符均是两个字节。但从Unicode 4.0开始,它已经不只65536个字符了,Unicode只是一个字符集名称,而UCS-2, UCS-4,UTF-8, UTF-16, UTF-32这些才是编码名称(当然,历史包袱总是存在的);
* UCS-2与UTF-16是不一样的,UCS-2固定采用两个字节,它不能表达Unicode 4.0之后增补的字符(当然,那些字符很生僻),而UTF-16里面每个字符可能是2或4个字符组成;
* UTF-8
** 从新的理论上而言,UTF-8应该是1-6个字符不等,但目前应该是1-3个字符就可以表达已有的字符了;
** UTF-8的优点
*** 如果原有数据大都采用ASCII表达,那么这些数据不用转换
*** 如果系统采用ASCII可以表达大多数数据,那么相对UCS-2,UTF-16这些节省空间;
*** 编码中字符边界很容易找到:以0开头的字节肯定是ASCII字符,最高位以11开头的字节肯定是字符的开头字节,以10开头的字节肯定是字符的后续字节;
*** 容错性强一些,偶尔一两个错误不会影响后面,原因同上(想咱们都碰到过GB2312/Big5的半个汉字问题带来的乱码问题吧)
*** 按字节流读取,不用考虑大端(big endian)/小端(little endian)问题
*** 字符串中不会出现0x00这样的字节(而UCS-2这些会),这样char *这样的方式表达缓冲区时不太容易导致错误
** UTF-8的缺点
*** 对于非ASCII字符,相对以前存储空间增加了,比如非英语的西欧字符集现在都需要两个字节了,而中文等很多都需要三个字节了;
*** 计算字符串长度比较麻烦,只能逐个统计;
** 综上,现在很多系统内部处理采用UCS-2,只在存储和数据交换中采用UTF-8
* Java以前内部全部采用Unicode(其实是UCS-2)来处理字符串,但Unicode 4.0以上的那些字符它不能处理。在Java 5.0中加入了一些奇怪的机制来解决这个问题;
* Python也不能同时支持UCS-2和UCS-4,只是可以在编译时挑选(~--enable-unicode=ucs2和~--enable-unicode=ucs4),看sys.maxunicode是否大于65535就知道是否是UCS-4了。我看Windows上的预编译版本是UCS-2(python2.5)的,而Linux上是UCS-4(Debian testing, python 2.4)。注意这两种版本在二进制上是不兼容的。
参考文档
* Joel Spolsky: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
* 每一个软件开发人员绝对必须掌握的关于 Unicode 和字符集的最基础的知识(上文的简体翻译,居然木野狐翻译的,好久不见他了)
* 对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16,GBK,GB2312的理解
<html>虽然我一直对于脚本语言比较偏爱,但也一直没把<a href="http://www.lua.org/">Lua</a>看上眼,认为它功能太弱了,只能“螺蛳壳里做道场”;而喜欢这个东西的似乎也都是搞C++的那些喜欢研究语言技巧的人。<p/>
但今天无意翻了一些<a href="http://wxlua.sourceforge.net/">wxLua</a>,对这个东西有了兴趣,然后又顺便看了一些Lua本身,发现这个东西以前还真没意识到它的价值。<p/>
先拿wxLua来说,wxWidgets有不少脚本语言的binding,从wxPython, wxRuby到<a href="http://wxjs.sourceforge.net/">wxJS</a>, 其实差别都不是特别大,但wxLua有些不同,至少它在使用模式上很适合于这样一种情况:快速开发一些小的程序(其它方面我还没来得及考虑,暂且不提)。<p/>
一 方面,适合这种情况的东西很少: 虽然可以用wxPython快速开发,但对于做一个程序来说,发布起来比较麻烦(py2exe还是有些够折腾的);Visual Basic和Delphi这类工具,可以快速开发,发布程序也方便(抛开VB程序采用的ActiveX库不谈),但它们是商业软件,同时又是庞然大物。所 以我看见一些同事用Excel的VBA来开发一些简单程序,也有比较geek的人学习<a href="http://www.autoitscript.com/autoit3/">AutoIt</a>。<p/>
另 一方面,wxLua自己也做得很适合这个。从规模上而言,wxJS比wxLua大不了多少,但wxLua将脚本解释器、wxWidgets对象全都做到了 一个可执行程序中,不需要任何动态库;它还提供了一个wxLuaFreeze工具,可以将Lua脚本跟这个解释器绑定到一个文件,用法相当简单,并且还可 以采用<a href="http://upx.sourceforge.net/">UPX</a>这类工具对最终程序进行“透明”压缩。<p/>
这样来看,lua算是一个非常好的胶水语言(glue language), 在表现上可以嵌入在程序中完全隐形,同时带给程序的累赘也少(至少我们的产品目前采用<a href="http://msdn.microsoft.com/scripting/">Active Scripting</a>就必须得将可脚本化的对象包装成COM对象,这个工作量可大了去了)。<p/>
不过,“五行拳”(<a href="http://203.208.37.104/search?q=cache:StJndPx8rq4J:forums.hipihi.com/upload/0/80/20080120/File_ff808081178d4e59011797e4b826355c_1200847999033.doc+Programming+Lua+%E8%A2%81%E6%89%BF%E5%BF%97&hl=zh-CN&ct=clnk&cd=6&gl=cn&st_usg=ALhdy2_NRH2k90sJmJZOIBZvl5Nx1H_O_g">Programming in Lua中文翻译版</a>中引用了一段金庸《碧血剑》里的文字,意在比喻“极寻常的拳术",只要练习得好了,”每一招均是含劲不吐,意在拳先,举手抬足之间隐含极浑厚的内力”)也有一点点不爽,比如我现在想在wxLua的脚本代码中操纵COM对象,就得仔细琢磨怎么将<a href="http://www.tecgraf.puc-rio.br/%7Ercerq/luacom/">LuaCOM</a>的代码合进来才行,回头要另外一个功能又要合代码,这种情况可能还不如py2exe方便了(不过还没琢磨过Lua的代码,不知道何如这些特性简单不)——但“需要什么才加什么”这种方式也挺不错的。</html>
巴蛮子,湖北施南府人氏,现在某个IT公司工作,本职工作是做测试工具。但他是个三脚猫,对很多东西电脑技术都有兴趣,比如<<tag delphi>>, <<tag script>>, <<tag Python>>, <<tag unix>>/<<tag linux>>/<<tag cygwin>>, <<tag gtk>>/<<tag gnome>>以及UI的可用性等,这里主要记录他工作之余的一些杂感。
在其它一些地方(比如MSN,Google Talk),他也常用“菠萝油王子”这个昵称,因为他很喜欢《麦兜故事2-菠萝油王子》这个故事,怕自己也“有一日,佢变做个佬”,也浑浑噩噩地过了多少年...
在电脑技术之外,他喜欢最喜欢爬山、美食和科幻。当然也喜欢旅游,但对各地风土人情的兴趣大于山水风光。
<html>
<script src="http://www.douban.com/service/badge/bamanzi/?show=collection&n=20&columns=4" type="text/javascript"></script>
</html>
<<tag systemConfig>>
编译一个[[wxWidgets内嵌wxPython的示例工程|http://svn.wxwidgets.org/viewvc/wx/wxPython/trunk/samples/embedded/]]时,编译器说需要python24_d.lib,因为懒得自己重新编译一遍python,在网上[[找到一个办法|http://public.kitware.com/pipermail/insight-users/2003-December/005866.html]]: 修改Python\include里面的python.h,把静态库都改成同一个(即将python24_d.lib改成python24.lib),其它.h文件也搜索Py_DEBUG,将两种模式下的处理搞成一致(比如不采用不同的引用计数函数),然后就OK了。
<<slider chkSlider 找不到python24_d.lib怎么办(罗嗦版) 下面是详细说明——我现在是越来越罗嗦了:-( >>
这几日在琢磨能不能直接采用wxPython搭建我们的下一版本的界面,各方面看都是我们要找的东西,除了一条: 如何将旧系统兼容进去(旧系统采用MFC+COM+Active Scripting技术搭建)。
于是我想先看看用MFC写的程序能不能集成wxPython,但google了半天没有任何信息,只好退而求其次查找wxWidgets上嵌入wxPython,倒是找到一个例子:
http://svn.wxwidgets.org/viewvc/wx/wxPython/trunk/samples/embedded/
它本来的Makefile是编译debug版的,这就需要python, wxWidgets和wxPython的debug版本动态库,好像网上对于Windows上都没有提供(不象Linux上还有python2.4- dbg, libwxgtk2.6-dbg可供安装),这就意味着必须完全自己来编译,编译时还有unicode,universal一大堆的选项,编译完了还有安装/配置的问题。
我烦了,就编译release版本吧,自己修改Makefile.vc,去掉了调试选项,编译出来了。但将 embeded.exe放到wxPython的目录运行,它跟我报怨说版本不匹配,wxPython的是"debug,unicode,Visual C++....",而embeded.exe是"no debug,unicode,Visual C++..."。奇怪,怎么预编译的wxPython居然还是debug版本?
没办法,又回头来编译debug版本,但折腾了半天,最后碰到一个python24_d.lib过不去。看来非得自己编译python不可了。我不死心,又在网上搜了一阵,找到一个办法: 修改Python\include里面的python.h,把静态库都改成同一个,其它.h文件也搜索Py_DEBUG,将两种模式下的处理搞成一致(比如不采用不同的引用计数函数),然后就OK了。
[[PyCon 2008|http://us.pycon.org/2008]]前两天开了, 但国内的Python社区似乎都没有见到什么人关注(至少在[[CPUG的Planet of Woodpecker.org|http://blog.woodpecker.org.cn/planet/]]上没人提到这个, Google了一下也没有多少中文信息, 倒是台湾的Python社区[[有网友说起|http://planet.python.org.tw/planet]],并且参会了)。
在[[Planet Python|http://planet.python.org]]上看到一篇[[PyCon 2008 notes|http://nedbatchelder.com/blog/200803/pycon_2008_notes.html]], 详细地说明了一下他参加的几个主题的内容,推荐!
* Using Python To Teach ~Object-Oriented Programming in ~CS1
* MPI Cluster Programming with Python and Amazon ~EC2
* Applying Expert System Technology to Code Reuse with Pyke
* Rich UI Webapps with ~TurboGears 2 and Dojo
* State of Django
* High performance Network IO with Python + Libevent
* Plenary: Twisted announcement: they have a foundation
* Plenary: You *can* Fool All of the People All of the Time
* Plenary Keynote: Intellectual Property and Open Source
* ~SQLAlchemy 0.4 and Beyond
* Managing Complexity (and testing)
* Using Grok to Walk Like a Duck
* Case Study of Python Application Development -- Humanized Enso
* To RE or not to RE -- Parsing text in Python
* Plenary: Making ~Client-Side Python Suck Less
* Plenary Keynote: Snake Charming the Dragon: the past, present and future of Python and Mozilla
* Plenary: OLPC Update
* Consuming HTML
* nose: testing for the lazy coder
* Introducing Agile Testing Techniques to the OLPC Project
<html>前几日一直在琢磨把俺的Blog迁移到这个玩意儿上来,好处在于:
<ul><li>所有文章都在一个网页内, 几百篇文章加起来也没有多大,而且要分多页也很简单
<li>这一个网页可以既是最终发布的地方,也是编撰系统
<li>随便找个能上传网页的地方就可以搭建blog了,万一都没有,在http://www.tiddlyspot.com上申请一个账户也行
<li>丰富的插件,自己想怎么玩就怎么玩
</ul>
我试验了一下,基本上满意,诸位可以看看初步效果<a href="http://bamanzi.tiddlyspot.com/">http://bamanzi.tiddlyspot.com/</a>。只是目前没有时间将一篇篇贴过来觉得麻烦,懒得动了。<p/>
如果将TiddlyWiki改造成更适合blog的系统,我的一些心得如下:<p/>
<ul><li>用<a href="http://ptw.sf.net/">RecentTiddlersPlugin</a>或者<a href="http://tiddlystyles.com/">WeblogPlugin</a>自动在页面打开时显示最近的文章</li><li>编辑DefaultTiddlers的内容,将要“置顶”的文章的名称列在这里,每次打开网页时都会显示它们</li>
<li>采用<a href="http://15black.bluedepot.com/twtests/tagcloud.htm">TagCloudPlugin</a>插件,在MainMenu中添加一个"标签云"</li><li>TW原本的风格是双击帖子就进入编辑模式,如果你觉得这样不适合于blog系统,可以在选项中将页面设置为网上只读模式,或者采用<a href="http://www.TiddlyTools.com/#ReplaceDoubleClick">ReplaceDoubleClick</a>将双击功能改造一下
</li><li><a href="http://www.TiddlyTools.com/#CommentScript">CommentScript</a>能增加留言功能(还没搞懂怎么让别人的留言写到网页)</li></ul><p/>另外下面这几个插件虽跟blog关系不大,也是应该有的:
<ul>
<li>从<a href="http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hans/locale.zh-Hans.js">这里</a>取得最新的中文翻译,将其作为插件加入,保存后再打开就会变成中文界面了
</li>
<li>添加<a href="http://www.tiddlytools.com/#GotoPlugin">GotoPlugin</a>或者<a href="http://www.tiddlytools.com/#SearchOptionsPlugin">SearchOptionsPlugin</a>,替代原来的搜索功能(原来的搜索会自动打开匹配结果,即使你在只输入了两个字符之后就停顿了一下...)
</li><li>添加<a href="http://tw.lewcid.org/#FullScreenPlugin">FullScreenPlugin</a>或者<a href="http://www.TiddlyTools.com/#ToggleLeftSidebar">ToggleLeftSideBar</a>这类插件(后者其实不是插件,而是借助InlineJavascriptPlugin实现功能的脚本),使得用户可以将文章最大化;添加<a href="http://gensoft.revhost.net/Collapse.html">CollapseTiddlerPlugin</a>或者[FoldHeadingPlugin|http://www.tiddlytools.com/#FoldHeadingsPlugin]] 使得用户可以将文章最小化(可以将帖子折叠起来,只显示标题)</li></ul>
<p/>
前面说的是对最终页面呈现有用的插件,但还需要东西来帮助我们撰写文章:
<ul><li><a href="http://aiddlywiki.sourceforge.net/wikibar_demo_2.html">WikiBarPlugin</a>可以在编辑文章时显示一个工具条(不过IE对CSS支持太差,工具条的下拉菜单显示不出来),免得你记不住那么多wiki语法(不同的wiki语法还不一样:-()——当然,宏还是应该记熟悉的</li><li><a href="http://www.tiddlytools.com">tiddlytools</a>提供的QuickEditPackage也可以提供WikiBar那样的工具条,但我还没搞明白怎么挪用过来:-(</li><li><a href="http://www.tiddlytools.com/#TiddlerTweakerPlugin">TiddlerTweakerPlugin</a>会允许你自行修改每个tiddler的作者、创建时间、修改时间,如果你想迁移你的blog系统肯定用得上
</li></ul><p/>但这几个插件体积都比较大,直接加到你的TW中会导致最后的HTML比较大,加载太慢,而放在网页上对阅读blog的朋友又没有什么作用,这就可以采用将这些插件用外部文件的方式来加载了,<a href="http://ptw.sourceforge.net/ptwe.html">LoadExtPlugin</a>就是干这个的(该网站还提供了一个不小的主题包)。
</html>