Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
/***
|''Requires''|codemirror.js|
|''License''|[[codemirror.js]]|
***/
//{{{
CodeMirror.defineMode("python",function(e,t){function r(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}function b(e,t){if(e.sol()){var r=t.scopes[0].offset;if(e.eatSpace()){var c=e.indentation();return c>r?y="indent":c<r&&(y="dedent"),null}r>0&&S(e,t)}if(e.eatSpace())return null;var h=e.peek();if(h==="#")return e.skipToEnd(),"comment";if(e.match(/^[0-9\.]/,!1)){var p=!1;e.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)&&(p=!0),e.match(/^\d+\.\d*/)&&(p=!0),e.match(/^\.\d+/)&&(p=!0);if(p)return e.eat(/J/i),"number";var d=!1;e.match(/^0x[0-9a-f]+/i)&&(d=!0),e.match(/^0b[01]+/i)&&(d=!0),e.match(/^0o[0-7]+/i)&&(d=!0),e.match(/^[1-9]\d*(e[\+\-]?\d+)?/)&&(e.eat(/J/i),d=!0),e.match(/^0(?![\dx])/i)&&(d=!0);if(d)return e.eat(/L/i),"number"}return e.match(v)?(t.tokenize=w(e.current()),t.tokenize(e,t)):e.match(a)||e.match(u)?null:e.match(o)||e.match(i)||e.match(l)?"operator":e.match(s)?null:e.match(m)?"keyword":e.match(g)?"builtin":e.match(f)?"variable":(e.next(),n)}function w(e){while("rub".indexOf(e.charAt(0).toLowerCase())>=0)e=e.substr(1);var r=e.length==1,i="string";return function(o,u){while(!o.eol()){o.eatWhile(/[^'"\\]/);if(o.eat("\\")){o.next();if(r&&o.eol())return i}else{if(o.match(e))return u.tokenize=b,i;o.eat(/['"]/)}}if(r){if(t.singleLineStringErrors)return n;u.tokenize=b}return i}}function E(t,n,r){r=r||"py";var i=0;if(r==="py"){if(n.scopes[0].type!=="py"){n.scopes[0].offset=t.indentation();return}for(var s=0;s<n.scopes.length;++s)if(n.scopes[s].type==="py"){i=n.scopes[s].offset+e.indentUnit;break}}else i=t.column()+t.current().length;n.scopes.unshift({offset:i,type:r})}function S(e,t,n){n=n||"py";if(t.scopes.length==1)return;if(t.scopes[0].type==="py"){var r=e.indentation(),i=-1;for(var s=0;s<t.scopes.length;++s)if(r===t.scopes[s].offset){i=s;break}if(i===-1)return!0;while(t.scopes[0].offset!==r)t.scopes.shift();return!1}return n==="py"?(t.scopes[0].offset=e.indentation(),!1):t.scopes[0].type!=n?!0:(t.scopes.shift(),!1)}function x(e,t){y=null;var r=t.tokenize(e,t),i=e.current();if(i===".")return r=t.tokenize(e,t),i=e.current(),r==="variable"||r==="builtin"?"variable":n;if(i==="@")return r=t.tokenize(e,t),i=e.current(),r==="variable"||i==="@staticmethod"||i==="@classmethod"?"meta":n;if(i==="pass"||i==="return")t.dedent+=1;(i===":"&&!t.lambda&&t.scopes[0].type=="py"||y==="indent")&&E(e,t);var s="[({".indexOf(i);return s!==-1&&E(e,t,"])}".slice(s,s+1)),y==="dedent"&&S(e,t)?n:(s="])}".indexOf(i),s!==-1&&S(e,t,i)?n:(t.dedent>0&&e.eol()&&t.scopes[0].type=="py"&&(t.scopes.length>1&&t.scopes.shift(),t.dedent-=1),r))}var n="error",i=new RegExp("^[\\+\\-\\*/%&|\\^~<>!]"),s=new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]"),o=new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"),u=new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"),a=new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"),f=new RegExp("^[_A-Za-z][_A-Za-z0-9]*"),l=r(["and","or","not","is","in"]),c=["as","assert","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","lambda","pass","raise","return","try","while","with","yield"],h=["abs","all","any","bin","bool","bytearray","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip","__import__","NotImplemented","Ellipsis","__debug__"],p={builtins:["apply","basestring","buffer","cmp","coerce","execfile","file","intern","long","raw_input","reduce","reload","unichr","unicode","xrange","False","True","None"],keywords:["exec","print"]},d={builtins:["ascii","bytes","exec","print"],keywords:["nonlocal","False","True","None"]};if(!t.version||parseInt(t.version,10)!==3){c=c.concat(p.keywords),h=h.concat(p.builtins);var v=new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))","i")}else{c=c.concat(d.keywords),h=h.concat(d.builtins);var v=new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))","i")}var m=r(c),g=r(h),y=null,T={startState:function(e){return{tokenize:b,scopes:[{offset:e||0,type:"py"}],lastToken:null,lambda:!1,dedent:0}},token:function(e,t){var n=x(e,t);return t.lastToken={style:n,content:e.current()},e.eol()&&e.lambda&&(t.lambda=!1),n},indent:function(e,t){return e.tokenize!=b?0:e.scopes[0].offset}};return T}),CodeMirror.defineMIME("text/x-python","python");
//}}}
!Info
This story was written prior to the possibility to compare the content of a tiddler using the _hash field.
!Intro
From: http://groups.google.com/group/tiddlyweb/browse_thread/thread/4330ff24c657716?hl=en
Part 1 is a user story, according to online/offline syncing
Part 2 is a rather technical description, how I think it can be
solved.
!Part 1
1) As a online user of TiddlySpace who wants to work offline I'd expect:
1.1) Pressing the download button, creates a file, that exactly contains the content, that I actually see in the browser.
2) As a offline user I'd expect:
2.1) I have one (big) file that contains my actual content.
2.2) Every "save tiddler" saves the file and creates a backup, if configured.
2.3) Adding new tiddlers is possible.
2.4) Adding new plugins is possible.
short) I want to work with it, as if it is a file TW.
3) As a offline user, preparing for syncing I'd expect:
3.1) Have a list function, that tells me which tiddlers have been added and/or been newly created. This is a convenience function, which would make me feel better.
4) As a offline user, connected to the internet, I'd expect
4.1) A "sync button" that creates a list new/modified (similar to 3.1)
4.2) The list lets me select tiddlers one by one or with "select all" button
4.3) Click push to server creates some info, what's going on eg: 10% fineshed, or syncing tiddler XXX ...
4.4) If finished creates a new list with
4.4.1) sync success: ...list...
4.4.2) not synced: ... list - because not selected by user ...
4.4.3) conflict -- described later
4.4.4) create a tiddler, that contains this protocol.
As a tiddlySpace user I'd be happy now. (Assuming 4.4.3 doesn't happen on a single user space)
!Part 2
5.1) As a experienced user at download, I'd wish, that the server gives me the smallest possible file. Everything, that I need to work offline. If offline, I don't need any plugins, that are only needed saving single tiddler to the server. I'd expect, that the server skips them. But this is only a nice to have :)
back to 4.4.3)
Only the conflict tiddlers are in the list. The rest is synced allready.
4.4.3.1 -- As an experienced user I know, that there is the possibility, that someone else edited a server side tiddler, that I want to upload now. But as a user, I think:"And .. what's the problem? Make sugestions, and I'll tell you what to do :)"
4.4.3.2 -- As a programmer I think "hell - What ever I suggest, there will be someone who doesn't like it"
4.4.3.3 -- As a programming user I'll tell you what I think, could work :)
I) Assuming that 1.1 is true. Worst case is mixed mode. The offline file contains private and public tiddlers. If a program can handle mixed mode, it also can handle public only or private only mode.
!!II) Basic Assumptions
II.1) Assuming, that a tiddler can be identified (ID) by server wide unique revision number [1].
II.2) Assuming, that revision number is only set by the server
II.3) Assuming, that modified timestamp is changed, if I edit a tiddler offline. revNo is _never_ changed offline
II.4) Assuming, that revision number is set to 00 for new offline tiddlers.
II.5) Assuming, that offline editing and creating sets a tiddler Syncflag dirty.
!!III) scenario:
{{{
online | privateRevNo modified | publicRevNo modified:
online | 11 2010.1.1 | 99 2009.9.9
Download logged in:
offline| privateRevNo modified
offline| 11 2010.1.1
I change the tiddler offline:
According to II.3 local TW doesn't change the RevNo but it changes the modified timestamp.
So I get
offline| privateRevNo modified
offline| 11 2010.9.9
}}}
According to II.2: If someone changes serverside tiddlers RevNo and modified are changed.
There are 8 possibilities.
<<<
{{{
(1) indicates changed
priv | pub | offline |
0 0 0 .. no need for syncing
0 0 1 ..
0 1 0 .. trivial do nothing
0 1 1 ..
1 0 0 .. trivial do nothing
1 0 1 ..
1 1 0 .. trivial do nothing
1 1 1 ..
}}}
<<<
Now remove the trivial possibilities according to II.5, because nothing changed offline.
<<<
{{{
check for difference in ID see: II.1
priv | pub | offline |
a) 0 0 1
b) 0 1 1
c) 1 0 1
d) 1 1 1
}}}
<<<
With the above cases, there is still the problem, that the offline version of the tiddler was cloned from private bag(see: III scenario). What, if it was cloned from public? (go on reading)
<<<
{{{
check for difference in ID see: II.1
(1) indicates changed
priv | pub | offline |
a) 0 0 1
}}}
<<<
According to II.2 revision number is only set by the server and, II.3 offline revNo is not touched if editing is done. It is possible to know, where the offline tiddler comes from.
<<<
{{{
if privRevNo = publicRevNo = offlineRevNo
-> suggest overwrite private
-> but allow overwrite public
else if privRevNo = offlineRevNo the tiddler was private
-> overwrite private
else if pubRevNo = offlineRevNo the tiddler was public
-> overwrite public
}}}
<<<
a) solved:
That's cool. its getting easyer.
But it can be all done in one run.
----
check for difference in ID see: II.1
<<<
{{{
(1) indicates changed
priv | pub | offline |
b) 0 1 1
c) 1 0 1
d) 1 1 1
if privRevNo = offlineRevNo the tiddler was private
-> overwrite private. (b)
else if pubRevNo = offlineRevNo the tiddler was public
-> overwrite public. (c)
else
-> Tell the user that (d) there is a conflict.
}}}
*Show Modifier and timestamp of private and public tiddler
*Mark overwrite private tiddler as default, but give the possibility:
**sync with private, public, don't sync
*Tell the user about revisions and diff
*Create a sync protocol tiddler
<<<
now combine a) with b)c)d)
[1] chris dent: revision number is unique to the server, and can be
used. http://groups.google.com/group/tiddlyweb/browse_thread/thread/d36cb1c...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<path id="iconSymbol" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m21.411,59.069,3.5152,4.3939,9.7922-11.675" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4" stroke-width="2.4000001" fill="none"/>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
<<tiddler FollowTemplate>>
@@Please do not modify this tiddler; it was created automatically upon space creation.@@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" class="smallOnActive">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<path id="iconSymbol" stroke-linejoin="round" d="m18.831,9.4156v10.985l-4.865,5.806" transform="matrix(0.8, 0, 0, 0.8, 13, 43)" stroke="#4d4d4d" stroke-linecap="round" stroke-width="3" fill="none" class="showSY"/>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
link: http://www.PayPal.com/
<<xList xCase "sort." "." "[tag[topMenu]]">>/%
see the descriptions about the above at: http://apm-plugins.tiddlyspot.com/#StylingPackage.
%/
! Pop Up Chat Space
<<tiddler "ChatUps##ChatUps">>
! List Talk/Chat Channels
<<tsScan url:"/search?q=title:* AND tag:talkChannel" template:"ChannelList##Template" sort:"server.bag">>
/%
! Template
<<view server.bag SiteIcon label:no width:24 height:24 preserveAspectRatio:yes>> <<view server.bag spaceLink title external:no>> in space <<view server.bag spaceLink>> talks about: - <<view talk.about.bag spaceLink talk.about.title external:yes>> in <<view talk.about.bag spaceLink external:yes>> space
!
{{{
<<tsScan url:"/search?q=title:* AND tag:talkChannel" template:"ChannelList##Template" sort:"server.bag">>
}}}
%/
In SearchShortcomings@cdent @cdent raises the question, how to build the next TS search interface. Also related to 20120508@cdent
! TS Search Thoughts
I think, we are all spoiled by a major search engine. So, what I'm really missing, is some "teaser" text, together with a search result. Eg: TW/TS activity list, just returns the tiddler title, the user and the space.
To decide, if this is important, I need to open the stuff.
!! Search Priority
I think TS should look more like a "forum" search.
* First imput works with the default settings
* and leads to result page with "advanced" settings.
!!! Example GitHub:
* The basic search is "simple"
* see: Search term - "tiddly" - https://github.com/search?q=tiddly&type=Everything&repo=&langOverride=&start_value=1
!!! Result
* Advanced Search Interface
* 5 Repositories with there Info text + some statistics.
* 5 Nickname + Full Name + basic Info
* 5 Source Files with 3-5 lines of source code near the match.
I like the resulting view. If the user isn't satisfied with the results, s/he can provide "better" search input.
!! Semantic - Syntactic
* As a plugin author, I'd have no problem to use 2 different search URI's, as long as the "syntax" is same for both.
* A big problem for "non english" users are typos in search terms. So the first input, imo should use "fuzzy" search settings.
!! Search Priority
* Since tiddler titles are often CamelCase, I think headings in tiddler text are as important as the tiddler title.
* I'm most interested in tiddlers, that are max. 1-2 month's old.
* Tags
** If a search term hits a tag and text -> high priority.
* Space names
** If a search term hits a space name I'd like to know it.
To be modified ...
! Finding a Participation Scheme for TiddlySpace
At the moment (2011.01.15) Steve Schneider seems to evaluate the possibilitis of TS. This info is partially in response to anticipatoryTransclusion@stevesuny at @stevesuny, without copying content from his space into mine.
My goal is, the content inside this tiddler should stay valid, even if it's ~TwinPage may disappear. Chris Dent named these type of tiddlers TwinPages@cdent in the context of ~TiddlySpace. Some more links, I found can be seen at: TwinPage@pmario
As I don't intend to change, this tiddler title again (without a good reason :), this scheme should make it possible for others, to create links to my content, without cloning it.
!! Tracking Communication
There have been many discussions, at the beginning of ~TiddlySpace, about "communication" with TS. See the topic started from ~@kosmaton [[HowDoISocialInTiddlySpace|http://pmario.tiddlyspace.com/#HowDoISocialInTiddlySpace]]. IMO until now, it isn't solved. There are several mechanisms in ~TiddlySpace, that are very close to a solution but polishing is highly needed.
<<tiddler TheUseOfLinkedTiddlersMacro@pmario>>
<<tiddler TheUseOfTsScanMacro@pmario>>
<<tiddler GetFollowersInformation@pmario>>
----
!!!!! note
I'll try to shorten this tiddler.
/%
<<slider chkTheUseOfLinkedTiddlerMacro "TheUseOfLinkedTiddlerMacro@pmario" "Show TheUseOfLinkedTiddlerMacro ยป" Show TheUseOfLinkedTiddlerMacro >>
%/
A little test using fancyBox plugin:
<<fancyBox button:"Apps" "loading.gif" label:"Open an iframe" href:"http://pmario.tiddlyspace.com/apps" defaults:"##Iframe">>/%
%/<<fancyBox button:"Account" "loading.gif" label:"Open an iframe" href:"http://pmario.tiddlyspace.com/_account" defaults:"PopApps##Iframe">>/%
%/<<fancyBox button:"Space" "loading.gif" label:"Open an iframe" href:"http://pmario.tiddlyspace.com/_space" defaults:"PopApps##Iframe">>
!Iframe
{{{
width: 95%
height: 95%
centerOnScroll: true
transitionIn: none
transitionOut: none
type: iframe
}}}
!!!!!!end
{{{
<<fancyBox button:"Apps" "loading.gif" label:"Open an iframe" href:"http://pmario.tiddlyspace.com/apps" defaults:"PopApps##Iframe">>
}}}
< <tiddler "Backstage##Menu">>
just a fast shot. I'll convert this tiddler into something similar to anticipatoryTransclusion@pmario.
~@stevesuny
* What is the reason, why you included the "system" space into your space. It is ''not'' needed.
----
in reply to [[Good Friday Morning!]]@stevesuny
>At some point, we've got our own theme built here, but I don't know how to put these things together in a theme. @pmario might help if we ask. Meantime, I think copying these will do it: CSidebarTools CSideBarTabs SideBarTabs SidebarTools and SideBarOptions?
You can contact me. {{{pmariojo at gmail dot com}}}
* IMO a "plugin space" is the way to go.
** You can include your C.... tiddlers (above) into a "plugin" space and take care, that this plugin spaces is included after neui-em space into your "target" space.
*** That will overwrite my settings and activate yours. ...
*** And it can be maintained in only one place.
** Be sure, you get rid of your individual tiddlers, in existing target spaces, that overwrite your plugin settings.
* See the section about the include mechanism at TiddlersRecipesAndBags@pmario to see how it works. hope this makes sense :)
> Work on understanding how to prevent certain tags from displaying? like topMenu and default? Is that even possible?
* You just need to create the "tag tidder" and tag this tiddler "excludeLists".
** eg: If you want to get rid of topMenu tiddler, create and tag it {{{exclideLists }}} it's gone from the tags tab.
** see: [[topMenu]]@pmario
3 possibilities: You can use all of them together
* excludeLists .. not shown in {{{<<list>>}}} macros eg: timeline
* excludeMissing .. not shown in the "missing" sidebar
* excludeSearch .. Search wont list theses tiddlers.
> Spend a bit of time investigating ViewTemplate, explore for moving tagged (?) to be above the public/private and the date (seems to me to be more important).
would be easy. contact me
> I think neui-theme uses the emastic system so maybe it is possible just to expand the left most part of the tiddler by a bit, so that there is more space for the tagged.
jup.
need to check it out.
<<tiddler FollowTemplate>>
Related to: https://github.com/Jermolene/TiddlyWiki5/issues/12
! TW5 Syntax Thoughts
* Reading the plain text source in TW5 should be easy.
At the moment all source text needs to be "compressed" to get nice rendering. It seems TW syntax wasn't designed with "readability" in mind. Markdown was and it got much traction lately.
But ... If you have a look at the [[Wiki Creole Specifikation|http://www.wikicreole.org/wiki/AllMarkup]] they seem to have used many aspects of TiddlyWiki. As all TWians know, TW syntax is quite usable.
!! Invisible markup
[[Invisible markup|http://www.wikicreole.org/wiki/InvisibleMarkup]] should have the same meaning. eg: {{{\n, 3 spaces, <tab>}}}
which would avoid stuff like:
{{{
<<tiddler myTiddler 'cssClass'>>/%
%/<<tiddler mySecondTiddler 'cssClass'>>
}}}
just to increase the source readability, but to avoid a {{{linebreak}}} between the two tiddlers.
If you need the tiddlers content separated just use a propper CSS definition {{{.cssClass}}}.
''Since the new *Template tiddlers seem to use TW syntax, creating a documented custom layout will be tricky''
eg ViewTemplate:
{{{
title: ViewTemplate
modifier: JeremyRuston
{{title{
<<view title>>}}}
/% some comment, what's going on %/
{{small{
<<view modifier link>> <<view modified date>> <<view tags>> <<button EditTiddler label:"edit" class:"btn btn-mini btn-primary">>}}}
/% my comment comes here %/
{{body{
<<view text wikified>>}}}
}}}
will produce a different result, than a version without TW comments, because of the hidden linebreaks {{{\n}}}.
!! Text Bolck Rendering
# {{{ {{{ }}}
# {{{ //{{{ }}}
# {{{ <!--{{{--> }}}
# {{{ /*{{{*/ }}}
At the goolge group there has been some discussion about [[block markup|http://groups.google.com/group/tiddlywikidev/browse_thread/thread/274ed6916fd295b9/d9494e4d9af845d1]]
Jeremy introduced {{{$$$.js}}} as a starting markup for "user defined" types. IMO it could be solved with
{{{
//{{{.js
or
//{{{.svg
or
<!--{{{.svg-->
or
/*{{{.css*/
or
//{{{.nestedSlider param1:aaa param2: bbb ...
not possible
{{{.js ... because this is valid stuff to create a span }}}
}}}
!! Fallback
If the renderer plugin for {{{//{{{.myType ... }}} is not installed, the fallback mechanism (TW) should just render the stuff as a {{{plain text}}} block.
!! New Text
* ... should get it's own rendering.
!! Tiddler Macro Extension
If {{{<<tiddler>>}}} macro is called with a blank section reference, it should transclude the section from the same tiddler.
eg:
{{{
<<tiddler "##test">>
/%
! test
some text
!
%/
}}}
* Projects@pmario
** For me it is an application plattform.
* I am using tiddlyspace to aggregate Information.
** eg: @news space. Even if others don't use it that much. It's set up, it works, it's easy to use (for me).
** I can design it, how I want it.
* I never had a public bookmarks repo.
** Since TiddlySpace I have one. There's not much in it but I like how it works.
Markup to porduce an invisibel description slice
{{{
/%
description: some text here
%/
}}}
Markup to porduce an invisibel section
{{{
/%
! SectionName
some text
some more text
! end
%/
}}}
''related''
http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki#TransclusionsInsideTables%20TstSliderViewCode
Do me a Favor
=============
You can do me a favor, and use one of my links below.
Push me at Ubuntu One
--------------------
If you don't have an `UbuntuOne` account, and you want to support this project, create one, using the link below:
You'll get 500MByte more disk space: https://one.ubuntu.com/referrals/referee/690716/ <br>
And me too :)
Push me at Drop Box
-------------------
If you don't have a `DropBox` account you can use the link below, to create one.
You'll get 500MByte more disk space: http://db.tt/qpWm38l <br>
And me too :)
Push me at Bit Casa
-------------------
If you don't have a `BitCasa` account you can use the link below, to create one.
I actually don't know, if we you get something for free. But there storage is infinite, so they should have something left :)
Use this link to create your account http://l.bitcasa.com/IBDGcJcC
Visit my Whishlist
------------------
Visit the my [Amazon Whishlist](http://www.amazon.de/registry/wishlist/3SV2ZNNBSMLN5/ref=cm_wl_sb_o?reveal=unpurchased&filter=all&sort=priority&layout=standard&x=12&y=9) and be generous :)
/***
|''Requires''|codemirror.js|
|''License''|[[codemirror.js]]|
***/
//{{{
CodeMirror.defineMode("javascript",function(e,t){function o(e,t,n){return t.tokenize=n,n(e,t)}function u(e,t){var n=!1,r;while((r=e.next())!=null){if(r==t&&!n)return!1;n=!n&&r=="\\"}return n}function l(e,t,n){return a=e,f=n,t}function c(e,t){var n=e.next();if(n=='"'||n=="'")return o(e,t,h(n));if(/[\[\]{}\(\),;\:\.]/.test(n))return l(n);if(n=="0"&&e.eat(/x/i))return e.eatWhile(/[\da-f]/i),l("number","number");if(/\d/.test(n))return e.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/),l("number","number");if(n=="/")return e.eat("*")?o(e,t,p):e.eat("/")?(e.skipToEnd(),l("comment","comment")):t.reAllowed?(u(e,"/"),e.eatWhile(/[gimy]/),l("regexp","string-2")):(e.eatWhile(s),l("operator",null,e.current()));if(n=="#")return e.skipToEnd(),l("error","error");if(s.test(n))return e.eatWhile(s),l("operator",null,e.current());e.eatWhile(/[\w\$_]/);var r=e.current(),a=i.propertyIsEnumerable(r)&&i[r];return a&&t.kwAllowed?l(a.type,a.style,r):l("variable","variable",r)}function h(e){return function(t,n){return u(t,e)||(n.tokenize=c),l("string","string")}}function p(e,t){var n=!1,r;while(r=e.next()){if(r=="/"&&n){t.tokenize=c;break}n=r=="*"}return l("comment","comment")}function v(e,t,n,r,i,s){this.indented=e,this.column=t,this.type=n,this.prev=i,this.info=s,r!=null&&(this.align=r)}function m(e,t){for(var n=e.localVars;n;n=n.next)if(n.name==t)return!0}function g(e,t,n,i,s){var o=e.cc;y.state=e,y.stream=s,y.marked=null,y.cc=o,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);for(;;){var u=o.length?o.pop():r?A:L;if(u(n,i)){while(o.length&&o[o.length-1].lex)o.pop()();return y.marked?y.marked:n=="variable"&&m(e,i)?"variable-2":t}}}function b(){for(var e=arguments.length-1;e>=0;e--)y.cc.push(arguments[e])}function w(){return b.apply(null,arguments),!0}function E(e){var t=y.state;if(t.context){y.marked="def";for(var n=t.localVars;n;n=n.next)if(n.name==e)return;t.localVars={name:e,next:t.localVars}}}function x(){y.state.context||(y.state.localVars=S),y.state.context={prev:y.state.context,vars:y.state.localVars}}function T(){y.state.localVars=y.state.context.vars,y.state.context=y.state.context.prev}function N(e,t){var n=function(){var n=y.state;n.lexical=new v(n.indented,y.stream.column(),e,null,n.lexical,t)};return n.lex=!0,n}function C(){var e=y.state;e.lexical.prev&&(e.lexical.type==")"&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function k(e){return function(n){return n==e?w():e==";"?b():w(arguments.callee)}}function L(e){return e=="var"?w(N("vardef"),j,k(";"),C):e=="keyword a"?w(N("form"),A,L,C):e=="keyword b"?w(N("form"),L,C):e=="{"?w(N("}"),B,C):e==";"?w():e=="function"?w(z):e=="for"?w(N("form"),k("("),N(")"),I,k(")"),C,L,C):e=="variable"?w(N("stat"),_):e=="switch"?w(N("form"),A,N("}","switch"),k("{"),B,C,C):e=="case"?w(A,k(":")):e=="default"?w(k(":")):e=="catch"?w(N("form"),x,k("("),W,k(")"),L,C,T):b(N("stat"),A,k(";"),C)}function A(e){return d.hasOwnProperty(e)?w(M):e=="function"?w(z):e=="keyword c"?w(O):e=="("?w(N(")"),O,k(")"),C,M):e=="operator"?w(A):e=="["?w(N("]"),H(A,"]"),C,M):e=="{"?w(N("}"),H(P,"}"),C,M):w()}function O(e){return e.match(/[;\}\)\],]/)?b():b(A)}function M(e,t){if(e=="operator"&&/\+\+|--/.test(t))return w(M);if(e=="operator")return w(A);if(e==";")return;if(e=="(")return w(N(")"),H(A,")"),C,M);if(e==".")return w(D,M);if(e=="[")return w(N("]"),A,k("]"),C,M)}function _(e){return e==":"?w(C,L):b(M,k(";"),C)}function D(e){if(e=="variable")return y.marked="property",w()}function P(e){e=="variable"&&(y.marked="property");if(d.hasOwnProperty(e))return w(k(":"),A)}function H(e,t){function n(r){return r==","?w(e,n):r==t?w():w(k(t))}return function(i){return i==t?w():b(e,n)}}function B(e){return e=="}"?w():b(L,B)}function j(e,t){return e=="variable"?(E(t),w(F)):w()}function F(e,t){if(t=="=")return w(A,F);if(e==",")return w(j)}function I(e){return e=="var"?w(j,R):e==";"?b(R):e=="variable"?w(q):b(R)}function q(e,t){return t=="in"?w(A):w(M,R)}function R(e,t){return e==";"?w(U):t=="in"?w(A):w(A,k(";"),U)}function U(e){e!=")"&&w(A)}function z(e,t){if(e=="variable")return E(t),w(z);if(e=="(")return w(N(")"),x,H(W,")"),C,L,T)}function W(e,t){if(e=="variable")return E(t),w()}var n=e.indentUnit,r=t.json,i=function(){function e(e){return{type:e,style:"keyword"}}var t=e("keyword a"),n=e("keyword b"),r=e("keyword c"),i=e("operator"),s={type:"atom",style:"atom"};return{"if":t,"while":t,"with":t,"else":n,"do":n,"try":n,"finally":n,"return":r,"break":r,"continue":r,"new":r,"delete":r,"throw":r,"var":e("var"),"const":e("var"),let:e("var"),"function":e("function"),"catch":e("catch"),"for":e("for"),"switch":e("switch"),"case":e("case"),"default":e("default"),"in":i,"typeof":i,"instanceof":i,"true":s,"false":s,"null":s,"undefined":s,NaN:s,Infinity:s}}(),s=/[+\-*&%=<>!?|]/,a,f,d={atom:!0,number:!0,variable:!0,string:!0,regexp:!0},y={state:null,column:null,marked:null,cc:null},S={name:"this",next:{name:"arguments"}};return C.lex=!0,{startState:function(e){return{tokenize:c,reAllowed:!0,kwAllowed:!0,cc:[],lexical:new v((e||0)-n,0,"block",!1),localVars:t.localVars,context:t.localVars&&{vars:t.localVars},indented:0}},token:function(e,t){e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation());if(e.eatSpace())return null;var n=t.tokenize(e,t);return a=="comment"?n:(t.reAllowed=a=="operator"||a=="keyword c"||!!a.match(/^[\[{}\(,;:]$/),t.kwAllowed=a!=".",g(t,n,a,f,e))},indent:function(e,t){if(e.tokenize!=c)return 0;var r=t&&t.charAt(0),i=e.lexical,s=i.type,o=r==s;return s=="vardef"?i.indented+4:s=="form"&&r=="{"?i.indented:s=="stat"||s=="form"?i.indented+n:i.info=="switch"&&!o?i.indented+(/^(?:case|default)\b/.test(t)?n:2*n):i.align?i.column+(o?0:1):i.indented+(o?0:n)},electricChars:":{}"}}),CodeMirror.defineMIME("text/javascript","javascript"),CodeMirror.defineMIME("application/json",{name:"javascript",json:!0});
//}}}
<<tiddler TEMPLATES##follow>>
/*{{{*/
Name:Automatic
Background: #e5f0e5
Foreground: #0e190f
PrimaryPale: #fcfdfc
PrimaryLight: #accfae
PrimaryMid: #4A6C4A
PrimaryDark: #000000
SecondaryPale: #fdfcfc
SecondaryLight: #cfacac
SecondaryMid: #a15d5c
SecondaryDark: #000000
TertiaryPale: #fcfcfd
TertiaryLight: #afaccf
TertiaryMid: #615ca1
TertiaryDark: #000000
/*}}}*/
respond to [[Not Lazy Enough]]@jon
<<<
In ServerSettings I set the experimental "lazy" setting to true.
When curling my space however, it shocked me to discover it was 862,444kb
<<<
* It may be the whole TiddlySpace "core" stuff, that is not compressed an not external, even if ServerSettings has {{{external: true}}}
* It would be nice to have some documentation for the {{{ServerSettings}}} parameteters, even if it is "alpha" or "beta" or what ever it is.
<<tiddler FollowTemplate>>
/***
|''Name''|RevisionsCommandPlugin|
|''Description''|provides access to tiddler revisions|
|''Author''|FND|
|''Contributors''|Martin Budden|
|''Version''|0.3.3|
|''Status''|@@beta@@|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/RevisionsCommandPlugin.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/plugins/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.6.0|
|''Keywords''|serverSide|
!Usage
Extend [[ToolbarCommands]] with {{{revisions}}}.
!Revision History
!!v0.1 (2009-07-23)
* initial release (renamed from experimental ServerCommandsPlugin)
!!v0.2 (2010-03-04)
* suppressed wikification in diff view
!!v0.3 (2010-04-07)
* restored wikification in diff view
* added link to side-by-side diff view
!To Do
* strip server.* fields from revision tiddlers
* resolve naming conflicts
* i18n, l10n
* code sanitizing
* documentation
!Code
***/
//{{{
(function($) {
jQuery.twStylesheet(".diff { white-space: pre, font-family: monospace }",
{ id: "diff" });
var cmd = config.commands.revisions = {
type: "popup",
hideShadow: true,
text: "revisions",
tooltip: "display tiddler revisions",
revTooltip: "", // TODO: populate dynamically?
loadLabel: "loading...",
loadTooltip: "loading revision list",
selectLabel: "select",
selectTooltip: "select revision for comparison",
selectedLabel: "selected",
compareLabel: "compare",
linkLabel: "side-by-side view",
revSuffix: " [rev. #%0]",
diffSuffix: " [diff: #%0 #%1]",
dateFormat: "YYYY-0MM-0DD 0hh:0mm",
listError: "revisions could not be retrieved",
handlePopup: function(popup, title) {
title = this.stripSuffix("rev", title);
title = this.stripSuffix("diff", title);
var tiddler = store.getTiddler(title);
var type = _getField("server.type", tiddler);
var adaptor = new config.adaptors[type]();
var limit = null; // TODO: customizable
var context = {
host: _getField("server.host", tiddler),
workspace: _getField("server.workspace", tiddler)
};
var loading = createTiddlyButton(popup, cmd.loadLabel, cmd.loadTooltip);
var params = { popup: popup, loading: loading, origin: title };
adaptor.getTiddlerRevisionList(title, limit, context, params, this.displayRevisions);
},
displayRevisions: function(context, userParams) {
removeNode(userParams.loading);
if(context.status) {
var callback = function(ev) {
var e = ev || window.event;
var revision = resolveTarget(e).getAttribute("revision");
context.adaptor.getTiddlerRevision(tiddler.title, revision, context,
userParams, cmd.displayTiddlerRevision);
};
var table = createTiddlyElement(userParams.popup, "table");
for(var i = 0; i < context.revisions.length; i++) {
var tiddler = context.revisions[i];
var row = createTiddlyElement(table, "tr");
var timestamp = tiddler.modified.formatString(cmd.dateFormat);
var revision = tiddler.fields["server.page.revision"];
var cell = createTiddlyElement(row, "td");
createTiddlyButton(cell, timestamp, cmd.revTooltip, callback, null,
null, null, { revision: revision });
cell = createTiddlyElement(row, "td", null, null, tiddler.modifier);
cell = createTiddlyElement(row, "td");
createTiddlyButton(cell, cmd.selectLabel, cmd.selectTooltip,
cmd.revisionSelected, null, null, null,
{ index:i, revision: revision, col: 2 });
cmd.context = context; // XXX: unsafe (singleton)!?
}
} else {
$("<li />").text(cmd.listError).appendTo(userParams.popup);
}
},
revisionSelected: function(ev) {
var e = ev || window.event;
e.cancelBubble = true;
if(e.stopPropagation) {
e.stopPropagation();
}
var n = resolveTarget(e);
var index = n.getAttribute("index");
var col = n.getAttribute("col");
while(!index || !col) {
n = n.parentNode;
index = n.getAttribute("index");
col = n.getAttribute("col");
}
cmd.revision = n.getAttribute("revision");
var table = n.parentNode.parentNode.parentNode;
var rows = table.childNodes;
for(var i = 0; i < rows.length; i++) {
var c = rows[i].childNodes[col].firstChild;
if(i == index) {
if(c.textContent) {
c.textContent = cmd.selectedLabel;
} else {
c.text = cmd.selectedLabel;
}
} else {
if(c.textContent) {
c.textContent = cmd.compareLabel;
} else {
c.text = cmd.compareLabel;
}
c.onclick = cmd.compareSelected;
}
}
},
compareSelected: function(ev) {
var e = ev || window.event;
var n = resolveTarget(e);
var context = cmd.context;
context.rev1 = n.getAttribute("revision");
context.rev2 = cmd.revision;
context.tiddler = context.revisions[n.getAttribute("index")];
context.format = "unified";
context.adaptor.getTiddlerDiff(context.tiddler.title, context,
context.userParams, cmd.displayTiddlerDiffs);
},
displayTiddlerDiffs: function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title += cmd.diffSuffix.format([context.rev1, context.rev2]);
tiddler.text = "{{diff{\n" + context.diff + "\n}}}";
tiddler.tags = ["diff"];
tiddler.fields.doNotSave = "true"; // XXX: correct?
if(!store.getTiddler(tiddler.title)) {
store.addTiddler(tiddler);
}
var src = story.getTiddler(userParams.origin);
var tiddlerEl = story.displayTiddler(src, tiddler);
var uri = context.uri.replace("format=unified", "format=horizontal");
var link = $('<a target="_blank" />').attr("href", uri).text(cmd.linkLabel);
$(".viewer", tiddlerEl).prepend(link);
},
displayTiddlerRevision: function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title += cmd.revSuffix.format([tiddler.fields["server.page.revision"]]);
tiddler.fields.doNotSave = "true"; // XXX: correct?
if(!store.getTiddler(tiddler.title)) {
store.addTiddler(tiddler);
}
var src = story.getTiddler(userParams.origin);
story.displayTiddler(src, tiddler);
},
stripSuffix: function(type, title) {
var str = cmd[type + "Suffix"];
var i = str.indexOf("%0");
i = title.indexOf(str.substr(0, i));
if(i != -1) {
title = title.substr(0, i);
}
return title;
}
};
var _getField = function(name, tiddler) {
return tiddler.fields[name] || config.defaultCustomFields[name];
};
})(jQuery);
//}}}
related to: http://groups.google.com/group/tiddlywiki/browse_thread/thread/5b5c0206c9f39e11?hl=en
!Needs
*InlineJavascriptPlugin
*MaloStyleSheet or EmasticPercent included in StyleSheet
*If you have small screen resolution, toggle sidebars first.
*ToggleLeftSidebarEm: <<tiddler ToggleLeftSidebarEm>> | ToggleRightSidebarEm <<tiddler ToggleRightSidebarEm>>
<<tiddler [[Temporary SideBySide##Code50]]>> <<tiddler [[Temporary SideBySide##Code33]]>> <<tiddler [[Temporary SideBySide##Code100]]>>
/*{{{*/
!Code50
<script label="click for 2 columns">
jQuery('.tiddler').each(function () {
var hasWrapper = jQuery(this).parent().hasClass('tidWrapper');
if (!hasWrapper)jQuery(this).wrap('<div class="tidWrapper" />');
});
jQuery('.tidWrapper').attr('class', 'tidWrapper dp50');
</script>
!Code33
<script label="click for 3 columns">
jQuery('.tiddler').each(function () {
var hasWrapper = jQuery(this).parent().hasClass('tidWrapper');
if (!hasWrapper)jQuery(this).wrap('<div class="tidWrapper" />');
});
jQuery('.tidWrapper').attr('class', 'tidWrapper dp33');
</script>
!Code100
<script label="click for 1 column">
jQuery('.tiddler').each( function () {
if (jQuery(this).parent().hasClass('tidWrapper')) jQuery(this).unwrap();
});
</script>
!end
/*}}}*/
Groupie is a message bouncing board ... To use it, create a tiddler named @groupie and tag it "list" ... Write some plain text into the @groupie tiddler ... At your homespace create a link like: List@groupie ... and click it. ... If you want to send some "News" to GroupieNews have a look at: http://pmario.tiddlyspace.com/#Groupie
In response to cdent's [[Prototype with SPA]]@cdent
jbl wrote at: [[Prototype with SPA]]@jrbl
<<<
cdent:
> In my experience the prototypes that we do in TiddlyWiki are often big enough that
> its almost like we may as well just stick with it, instead of potentially throwing it
> away because there's so much effort involved...
jrbl:
>This reminds me of something I read recently that I shared with my coworkers, and which I think may be of value to keep in mind. Please see RefactoringTowardsDoomsdayDevices.
<<<
jrbl points to an incredible piece of work from "Bradley W. Schenck"
jrbl's [[RefactoringTowardsDoomsdayDevices]]@jrbl
<<<
jrbl
>A lesson about software refactoring (and many other important things in life), from
[[The Lair of the Clockwork Book|http://thrilling-tales.webomator.com/the-lair-of-the-clockwork-book/014]] Bradley W. Schenk
>Sometimes we find ourselves in a position so incredibly bad - so apparently insane, in fact - that we can't understand how we got from Point A to Point B. The reason we can't understand this is that Point A was something as simple as "I'd better get out of bed now", while Point B is something as strange as "I guess the only way out of this is to take my Doomsday Machine into a near solar orbit, and then heave it into the Sun."
<<<
----
All of this is quite interesting, how a fiction story "seems to" fit for software development.
''Now I'm changing the point of view.''
Having a closer look^^1^^ to the [[The Lair of the Clockwork Book|http://thrilling-tales.webomator.com/the-lair-of-the-clockwork-book/014]] I saw, that it is possible, that readers can "comment". Which I find quite unusual for sites like this. It points out, that the author is interested in feedback, about any single page. It turns out, that readers use it. "The Lair of the Clockwork Book" is a serialized story.
Now have a look at an interactive story like [[Toaster With Two Brains|http://thrilling-tales.webomator.com/toaster-with-two-brains-part-one/00_01]], where you can decide, which way you want to go (see second page). Which character, you as a reader want to follow. ...
And now think about a system like ~TiddlySpace, where you as an author have the possibility to include space links, that automatically display content from other spaces, not limited to yours. The author can decide, to which space s/he wants to link. ...
Rewriting the paragraph above
>Sometimes we find ourselves in a position so incredible - so apparently insane, in fact - that we can't understand how we got from Point A to Point B. The reason we can't understand this is that Point A was something as simple as "I'd better get out of bed now", while Point B is something as strange as "I guess the only way out, is to take my [[Doomsday Machine|TiddlySpace]] into a near solar orbit, //and see it shine//."
1) Having a closer look
- ~RightClick: "View the Sorce Code"
/***
|''Name''|BinaryTiddlersPlugin|
|''Description''|renders base64-encoded binary tiddlers as images or links|
|''Author''|FND|
|''Version''|0.3.2|
|''Status''|@@beta@@|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/BinaryTiddlersPlugin.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5|
!Code
***/
//{{{
(function($) {
var ctfield = "server.content-type";
var plugin = config.extensions.BinaryTiddlersPlugin = {
isWikiText: function(tiddler) {
var ctype = tiddler.fields[ctfield];
if(ctype) {
if (ctype == 'text/x-tiddlywiki') return true;
return !this.isBinary(tiddler) && !this.isTextual(ctype);
} else {
return true;
}
},
// NB: pseudo-binaries are considered non-binary here
isBinary: function(tiddler) {
var ctype = tiddler.fields[ctfield];
return ctype ? !this.isTextual(ctype) : false;
},
isTextual: function(ctype) {
return ctype.indexOf("text/") == 0
|| this.endsWith(ctype, "+xml")
|| ctype == 'application/json'
|| ctype == 'application/javascript';
},
endsWith: function(str, suffix) {
return str.length >= suffix.length &&
str.substr(str.length - suffix.length) == suffix;
},
isLink: function(tiddler) {
return this.isBinary(tiddler) && tiddler.text.indexOf("<html>") != -1
}
};
// Disable edit for linked tiddlers (for now)
// This will be changed to a GET then PUT
config.commands.editTiddler.isEnabled = function(tiddler) {
var existingTest = config.commands.editTiddler.isEnabled;
if (existingTest) {
return existingTest && !plugin.isLink(tiddler);
} else {
return !plugin.isLink(tiddler);
}
};
// hijack text viewer to add special handling for binary tiddlers
var _view = config.macros.view.views.wikified;
config.macros.view.views.wikified = function(value, place, params, wikifier,
paramString, tiddler) {
var ctype = tiddler.fields["server.content-type"];
if(params[0] == "text" && ctype && ctype !== 'text/x-tiddlywiki' && !tiddler.tags.contains("systemConfig") && !plugin.isLink(tiddler)) {
var el;
if(plugin.isBinary(tiddler)) {
var uri = "data:%0;base64,%1".format([ctype, tiddler.text]); // TODO: fallback for legacy browsers
if(ctype.indexOf("image/") == 0) {
el = $("<img />").attr("alt", tiddler.title).attr("src", uri);
} else {
el = $("<a />").attr("href", uri).text(tiddler.title);
}
} else {
el = $("<pre />").text(tiddler.text);
}
el.appendTo(place);
} else {
_view.apply(this, arguments);
}
};
// hijack edit macro to disable editing of binary tiddlers' body
var _editHandler = config.macros.edit.handler;
config.macros.edit.handler = function(place, macroName, params, wikifier,
paramString, tiddler) {
if(params[0] == "text" && plugin.isBinary(tiddler)) {
return false;
} else {
_editHandler.apply(this, arguments);
}
};
// hijack autoLinkWikiWords to ignore binary tiddlers
var _autoLink = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function() {
return plugin.isWikiText(this) ? _autoLink.apply(this, arguments) : false;
};
})(jQuery);
//}}}
$(document).ready ( function () {
// done with CSS
// $('.meta').hide();
// $('#header').hide()
var li = $('.autoload li a');
// console.log(li);
li.each( function(i, el) {
// console.log($(el).attr('href'));
var x = {};
x.url= $(el).attr('href');
x.success= function(data, status){
$(data).find('.tiddler').addClass('dp100').find('.meta').hide().end()
.appendTo('#tiddlertext')
}
$.ajax(x);
})
// $('#container').toggleClass('outerRim').toggleClass('dp100');
$('#article').toggleClass('dp100');
//jQuery('#header').attr('Class','').addClass('clear');
// $('#header').toggleClass('rim').toggleClass('dp100').addClass('clear');
// $('#header').toggleClass('dp100').addClass('clear');
$('#tiddlertext').addClass('clear');
// var tids = jQuery('#tiddlertext .tiddler');
// tids.toggleClass('dp50');
})
Unless you're delighted with the default theme you can make some quick changes by generating a new random color palette, hit this button to cycle through some alternatives.
<<RandomColorPaletteButton saturation_pale:0.67 saturation_light:0.53
saturation_mid:0.43 saturation_dark:0.06 pale:0.99 light:0.85 mid:0.5 dark:0.31>>
You can also change the look and feel completely by installing a new theme. To do this, find one you like in the @themes space, note down the name, and include it in this space by going to the space menu. You can reach the space menu by clicking on the blue and pink circle at the top-right of the page and chooshing "THIS SPACE". Here are a few to check out:
* @pip
* @caspian-ii
* @basalt
* @simplicity
* @cheesecake
* @jelly-doughnut
(//Note that if you are using a custom TiddlySpace install, these themes may not be present.//)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="918 510 14 14" width="14pt" height="14pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2010-06-06 13:07Z</dc:date><!-- Produced by OmniGraffle Professional 5.2.2 --></metadata><defs><radialGradient cx="0" cy="0" r="1" id="Gradient" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="white"/><stop offset="1" stop-color="#2b2b2b"/></radialGradient><radialGradient id="Obj_Gradient" xl:href="#Gradient" gradientTransform="translate(922.3752 513.7837) scale(11.4739436)"/></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><g><path d="M 929.6952 512.9018 C 927.1568 510.36337 923.0412 510.36337 920.5028 512.9018 C 917.9644 515.4402 917.9644 519.5558 920.5028 522.09418 C 923.0412 524.63257 927.1568 524.63257 929.6952 522.09418 C 932.2336 519.5558 932.2336 515.4402 929.6952 512.9018 M 925.099 515.7425 L 927.17633 513.66516 L 928.9318 515.42065 L 926.8545 517.498 L 928.9318 519.57532 L 927.17633 521.3308 L 925.099 519.25348 L 923.02167 521.3308 L 921.2662 519.57532 L 923.3435 517.498 L 921.2662 515.42065 L 923.02167 513.66516 Z" fill="url(#Obj_Gradient)"/></g></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#CC9900" offset="0"/>
<stop id="stop2" stop-color="#E8D18B" offset="0.66462"/>
<stop id="stop3" stop-color="#CC9900" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4">
<path id="path2868" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m54.317,7.6768a1.9973,1.9973,0,1,1,-3.9947,0,1.9973,1.9973,0,1,1,3.9947,0z" transform="matrix(0.8, 0, 0, 0.8, -13.3206, 45.4412)" stroke-width="2" fill="none"/>
<path id="path2870" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m28.659,61.002,1.5965,3.6122,3.918-0.52745,0.36073,2.2515m-14.924-6.2337,0.69646,2.1742,4.0617-1.7571,3.9354,0.03647" stroke-width="2.4" fill="none"/>
<path id="path2872" stroke-linejoin="round" style="stroke-dasharray:none;" d="m30.528,55.591,3.4621,1.1984-1.7754,2.7075" stroke-width="2.4" fill="none"/>
<path id="path2874" stroke-linejoin="round" style="stroke-dasharray:none;" d="m26.399,55.461-3.7651,0.63128-1.5048-3.1324" stroke-width="2.4" fill="none"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
There are a lot of interesting people using ~TiddlySpace that you might like to keep track of and interact with. There are a number of ways of doing this.
If you see a number in the speech bubble in one of your tiddlers, it means that someone is writing about the same thing as you. You can find out what they're saying by clicking on it. Likewise, if you see something interesting in someone else's space, you can respond to it and write up your own thoughts on the subject by clicking "Reply to this tiddler".
Additionally, if you find anyone interesting, or you find an interesting looking space and you'd like to know when it's changed, you can "follow" that space. To do this, simply create a tiddler with the title: {{{@space-name}}} and tag it {{{follow}}}. If you want, you can store some notes about that space in the body of the tiddler.
If you then want to know what happening, simply [[include|How do I include/exclude spaces?]]@docs the @tivity space and then visit your activity stream at [[/activity|/activity]], or just visit the @tapas space directly.
!Not sure who to follow?
Here's a few suggestions:
* @fnd
* @cdent
* @pmario
* @bengillies
* @dickon
As [[SinglePageModePlugin|http://www.tiddlytools.com/#SinglePageModePlugin]] does this allready, it should be easy to implement.
<<tiddler SideBarTabs>>
/%
*Renaming this tiddler, will make the right sidebar invisible.
*Using this tiddler with the theme, makes it possible to keep the original SideBarTabs tiddler.
!!!old content
<<tiddler SidebarButtons>>
<<slider chkSliderSideBarTabs SideBarTabs "Index ยป" "display the timeline">>
%/
/*{{{*/
[[FancyBoxStyleSheet]]
#app-picker_ {
display: none;
}
.dpfl {float: left;}
.dp49 {
display: inline; width:49%; *width:48.9%
}
.CodeMirror {
background: [[ColorPalette::PrimaryPale]];
}
.activeline {background: #f0fcff !important;}
.notLoaded {
background-image: URL('loading.gif');
background-repeat:no-repeat;
background-position:center;
}
.spaceName .siteIcon {
display: inline;
}
.header {
background: [[ColorPalette::PrimaryMid]]; /* old browsers */
background: -moz-linear-gradient(top, [[ColorPalette::PrimaryLight]] 0%, [[ColorPalette::PrimaryMid]] 45%, [[ColorPalette::PrimaryDark]] 100%); /* firefox */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,[[ColorPalette::PrimaryLight]]), color-stop(37%,[[ColorPalette::PrimaryMid]]), color-stop(100%,[[ColorPalette::PrimaryDark]])); /* webkit */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='[[ColorPalette::PrimaryLight]]', endColorstr='[[ColorPalette::PrimaryDark]]',GradientType=0 ); /* ie */
min-height: 7.5em;
}
#rightSign {
position: absolute;
right: 0;
opacity: .6;
}
#leftSign {
position: absolute;
opacity: .6;
left:0;
}
#inside {
width: 95%;
margin-left: auto;
margin-right: auto;
}
.sanitized {
border: 1px dotted blue;
}
/*Vertical tabs*/
.vTabs .tabset {
float:left;
display:block;
padding-left: 10px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 5px;
margin-top:0;
min-width:120px;
border:none;
}
.vTabs .tabset .tab {
display:block;
text-align:left;
padding-left: 10px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 5px;
margin:0 1px 1px 0;
border:none;
}
.vTabs .tabContents {
border:none;
margin-left:129px;
max-width:88%;
padding-left: 1em;
}
.vTabs .tabContents .tabContents {
border:none;
background:transparent;
}
a.externalLink:after {
display: inline-block;
content: "";
width: 12px;
height: 8px;
background: transparent url(data:image/gif;base64,R0lGODlhCAAIAIABAABmZv///yH5BAEKAAEALAAAAAAIAAgAAAIPjAMJd5q2HoQLsTpto84UADs=) no-repeat center;
}
a.externalLink:hover:after {
display: inline-block;
content: "";
width: 12px;
height: 8px;
background: url(data:image/gif;base64,R0lGODlhCAAIAIAAAP///////yH5BAEKAAEALAAAAAAIAAgAAAIPjAMJd5q2HoQLsTpto84UADs=) no-repeat center;
}
a.externalLink {
text-decoration:none;
}
/*}}}*/
|''Name:''|[[TWDefaultTheme]]|
|''Description:''|Your description here!|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspot.com]]|
|''Gen.Description:''|Automatically generated from: TWDefaultThemeProject|
|''PageTemplate:''|PageTemplate|
|''ViewTemplate:''|ViewTemplate|
|''EditTemplate:''|EditTemplate|
|''RevisionTemplate:''|RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
!StyleSheet
/*{{{*/
/* horizontal main menu stuff if created by list */
.noBullets a{
padding-top: 0.2em;
padding-bottom: 0.2em;
}
.noBullets ul,
.noBullets ol {
list-style:none;
padding:0;
margin: 0;
}
.noBullets li {
float: left;
}
[[StyleSheetTiddlySpace]]
/*}}}*/
* GotoPlugin,
* SearchOptionsPlugin,
* TagglyTaggingPlugin,
* HideWhenPlugin,
* SelectThemePlugin,
* StoryGlueMacro,
* SelectStoryMacro,
* NavigationMacro,
Sorted by priority.
/***
|''Name''|CMEditCommands|
|''Description''|Opens a tiddler in edit mode and starts CodeMirror editor.|
|''Version''|0.1.3|
|''Date''|2012-03-13|
|''Status''|''beta''|
|''Source''|https://github.com/pmario/tw.CodeMirrorPlugin|
|''License''|CC-BY-SA|
|''CoreVersion''|2.5|
|''Requires''|zCodeMirrorPlugin|
|''Keywords''|toolbar command code mirror codemirror edit|
!!!Description
<<<
To use this new toolbar command you have to add {{{cmEdit}}} to ToolbarCommands tiddler
eg:
{{{
|~ViewToolbar|tagSearch cmEdit +editTiddler ...
}}}
<<<
!!! History
<<<
* V 0.1.3 2012-03-13
** Added functions to make editor height persistent.
** + bug fixes introduced with V 0.1.2
* V 0.1.1
** Initial release
<<<
!!!Code
***/
//{{{
config.commands.cmEdit = {
text: "cmEdit",
tooltip: "Edit tiddler with CodeMirror editor!",
readOnlyText: "view",
readOnlyTooltip: "View the source of this tiddler using CodeMirror"
};
config.commands.cmSave = {
text: "cmSave",
tooltip: "Save tiddler, when CodeMirror editor is used!",
isEnabled: function(tiddler) {
return (!readOnly);
}
};
config.commands.cmEdit.handler = function(event,src,title)
{
// needed to get the original textarea dirty, after first time editing.
var cmOnChange = function(cmEditor) {
if (!cmEditor.dirty) {
cmEditor.dirty = true;
cmEditor.save();
}
};
// readOnly can't be set by config tidder.
// TODO onChange will need special handling. aka Hijacking if config also contains a onChange
var cmOptions = {
'readOnly': readOnly,
onChange: cmOnChange
};
// define var shortcuts
var cm = config.tools.cm;
var conf = cm.conf;
var tags = [], tl, mode;
// read CodeMirrorConfig tiddler and write to global conf var
cm.init();
var modes = CodeMirror.listModes();
// TODO post to mailing list about it ?! It makes handling the library more difficult.
var mimes = cm.listMimeNames();
// doesn't set tid if title is a shadow tiddler
var tid = store.getTiddler(title);
// set global settings
jQuery.extend(cmOptions, conf['global']);
// shadow tiddlers don't have tags, fields ...
if (tid && tid.fields) {
if (tid.fields['server.content-type'] && mimes.contains(tid.fields['server.content-type'])) {
mode = cm.getModeObject(tid.fields['server.content-type']);
jQuery.extend(cmOptions, conf[mode.name]);
jQuery.extend(cmOptions.mode, mode);
}
if (tid.fields['content-type'] && mimes.contains(tid.fields['content-type'])) {
mode = cm.getModeObject(tid.fields['content-type']);
jQuery.extend(cmOptions, conf[mode.name]);
jQuery.extend(cmOptions.mode, mode);
}
for (var i=0; i < modes.length; i += 1) {
if (conf[modes[i]] && conf[modes[i]].tags) {
tags = conf[modes[i]].tags.split(' ');
tl = tags.length;
// there is no need to know, which tag, was the one, that was found.
// it's important, that one was found.
for (var j=0; j < tid.tags.length; j += 1) {
tags.pushUnique(tid.tags[j]);
}
// if one tag is the same, pushUnique above will eliminate one or more tags.
if ((tl + tid.tags.length) != tags.length) {
jQuery.extend(cmOptions, conf[modes[i]]);
break; // modes.length loop. first found wins.
}
} // if
} // for
if (tid.fields['cm.height']) {
jQuery.extend(cmOptions, {cmHeight: tid.fields['cm.height']});
} // TODO TypeChooser and cmEdit should use the same functions. refactoring needed.
} // if tid
// if no mode was found, init with null -> text/plain
if (!cmOptions.mode) {
jQuery.extend(cmOptions, conf['null']);
}
// call the TW default editor
config.commands.editTiddler.handler.call(this,event,src,title);
// find the default editor
var textArea = jQuery(story.getTiddler(title)).find('textarea[edit=text]');
// create the cm editor
cm.startEditor(textArea, cmOptions);
return false;
};
config.commands.cmSave.handler = function(event,src,title)
{
var text = jQuery(story.getTiddler(title)).find('textarea[edit=text]');
var editor = jQuery(text[0]).data('editor');
if (editor) {editor.save();}
config.commands.saveTiddler.handler.call(this,event,src,title);
return false;
};
//}}}
! Example
<html>
<style>
.dp20, .dp25, .dp33,.dp50,
.dp100{float:left; display: inline; *margin-left:-0.04em; } /* IE margin hack */
.dpfr{float:right;}
/* dp = div percet */
.dp20{width:20%;} .dp25{width:25%;} .dp33{width:33.33%;} .dp50{width:50%;} .dp100{width:100%;}
.clear{ clear:both;}
.dp50 {border: none;}
.outerRim {
position: relative;
width: 520px;
background-color: #E0E0E0;
background-color: rgba(255, 255, 255, 0.7);
padding: 10px;
margin: auto;
padding: 10px;
margin-top: 10px;
border: 2px solid black;
}
.rim {
width: 556px;
margin-left: -18px;
-webkit-box-shadow: 0px 1px 1px #606A73;
position: relative;
background-color: #DCE7F1;
}
</style>
<div class="gradient"></div>
<div id="container" class="outerRim">
<div id="header" class="rim">
<h1>Header Title</h1>
</div>
<div id="article">
<div id="tiddlertext">
<div class="tiddler">
<div id="text-html" class="main section"><h1>Tiddler 1</h1><p>Some text</p></div>
</div>
<div class="tiddler">
<div id="text-html" class="main section"><h1>Tiddler 2</h1><p>Some text inside tiddler 2</p></div>
</div>
</div>
</div>
</div>
</html>
<script label="toggle layout">
// jQuery('#container').attr('class','dp100');
jQuery('#container').toggleClass('outerRim').toggleClass('dp100');
//jQuery('#header').attr('Class','').addClass('clear');
jQuery('#header').toggleClass('rim').toggleClass('dp100').addClass('clear');
jQuery('#tiddlertext').addClass('clear');
var tids = jQuery('#tiddlertext .tiddler');
tids.toggleClass('dp50');
</script>
!Code
<!--{{{-->
<html>
<style>
.dp20, .dp25, .dp33,.dp50,
.dp100{float:left; display: inline; *margin-left:-0.04em; } /* IE margin hack */
.dpfr{float:right;}
/* dp = div percet */
.dp20{width:20%;} .dp25{width:25%;} .dp33{width:33.33%;} .dp50{width:50%;} .dp100{width:100%;}
.clear{ clear:both;}
.dp50 {border: none;}
.outerRim {
position: relative;
width: 520px;
background-color: #E0E0E0;
background-color: rgba(255, 255, 255, 0.7);
padding: 10px;
margin: auto;
padding: 10px;
margin-top: 10px;
border: 2px solid black;
}
.rim {
width: 556px;
margin-left: -18px;
-webkit-box-shadow: 0px 1px 1px #606A73;
position: relative;
background-color: #DCE7F1;
}
</style>
<div class="gradient"></div>
<div id="container" class="outerRim">
<div id="header" class="rim">
<h1>Header Title</h1>
</div>
<div id="article">
<div id="tiddlertext">
<div class="tiddler">
<div id="text-html" class="main section"><h1>Tiddler 1</h1><p>Some text</p></div>
</div>
<div class="tiddler">
<div id="text-html" class="main section"><h1>Tiddler 2</h1><p>Some text inside tiddler 2</p></div>
</div>
</div>
</div>
</div>
</html>
<script label="toggle layout">
// jQuery('#container').attr('class','dp100');
jQuery('#container').toggleClass('outerRim').toggleClass('dp100');
//jQuery('#header').attr('Class','').addClass('clear');
jQuery('#header').toggleClass('rim').toggleClass('dp100').addClass('clear');
jQuery('#tiddlertext').addClass('clear');
var tids = jQuery('#tiddlertext .tiddler');
tids.toggleClass('dp50');
</script>
<!--}}}-->
! My Motivation
I beleve, aggregating, structuring and refactoring information are essential knowledge building processes. I beleve, ~TiddlyWiki, ~TiddlyWeb and ~TiddlySpace are tools to build, connect and share our knowledge in ways we think.
I love communicating. I love story telling and it turns out, that I still love programming :) So I want to help the community to create a better system. To make it usable for "the masses".
To do so, it is possible for me, to create specialiced ~HowTo Videos. I like to create step by step howTos. I can help with (new) plugins, themes and working examples.
For me, the ~TiddlySpace communication aspect, that is important to get feedback and others opinions, to build up new knowledge, isn't strong enough. I want, that it feels right and I want to help, to extend these functions.
Providing help to the tiddly community is fun, but there is also a lot of blood, sweat and tears involved. If one of my projects, plugins, examples or group responses did make your live easier or your ~TiddlyWiki more fun to use, I'm proud โ but thirsty ;)
If you want to help me to dedicate even more power and time to the community, you can make a donation via PayPal.
<html><style>.inline{display:inline;}</style>
<form class="inline" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="4YFEB7GZWN9NL">
<input type="image" src="https://www.paypalobjects.com/en_GB/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal โ The safer, easier way to pay online.">
<img alt="" border="0" src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif" width="1" height="1">
</form></html> or [[you do me a favor|http://pmario.tiddlyspace.com/do-me-a-favor]] - ''Thank you very much!''
If you want to dedicate your sensible donation to a specific project or problem you have, just use this button and drop me a line at - pmariojo (at) gmail.com
----
Have a look at my projects tidder.
have fun!
mario
Search
<<gotoTiddler search inputstyle:"width:90%" liststyle:"z-index: 5;">>
<<tiddler FollowTemplate>>
/***
|''Name:''|XListPlugin|
|''Description:''|Provides a {{{<<xList>>}}} macro, that prepares the list for drag and drop sorting|
|''Author:''|Mario Pietsch|
|''Version:''|0.2.0|
|''Date:''|2010.08.03|
|''Status:''|''beta''|
|''Source:''|http://apm-plugins.tiddlyspot.com/#XListPlugin|
|''License''|[[MIT License]]|
|''CoreVersion:''|2.5.0|
|''Requires:''|XCaseListPlugin |
|''Documentation:''|this file|
|''Keywords:''|list extended sort filter|
!!!Description
<<<
This macro is only needed if you want to use StylingPackage!
If you call {{{ <<xList>> }}} without any parameter you will get a non sortet list of all tiddlers.
!!!!UseCase
{{{
<<xList xCase [prefix] [regExp] [tag]>>
}}}
>*prefix .. can be any string. Default is "sort."
>*regExp .. can be any valid regExp, that runs against the tiddler title. Default is "." (any char except linebreaks)
>*tag .. "[tag[myTag]]" ''If you have spaces inside the tag, it has to be covered inside double quotes !!''
{{{
eg:
<<xList xCase "sort." "." "[tag[with spaces]]">>
}}}
>The above configuration will produce a custom field named {{{sort.with.spaces}}}. Because custom fields have to be lower case and spaces are not allowed. Since the tag name is used for the custom field, one tiddler can be part of different sorted lists.
<<<
!!!ToDo
<<<
*Test together with MatchTagsPlugin
<<<
!!!History
<<<
*V 0.2.0 - 2010.08.03
**initial release
<<<
***/
/*{{{*/
config.macros.xList = {};
config.macros.xList.xCase = config.macros.list.xCase;
config.macros.xList.handler = function(place,macroName,params)
{
var type = params[0] || "xCase";
var sortField = params[1] || "sort.";
var tag = params[2] || ".";
var tag = params[3] || "";
tag = tag.toLowerCase();
sortField = sortField.toLowerCase();
var match = tag.match(/tag *\[(.+) *\] *\]/im); // get the tag text
if (match != null) tag = match[1];
var res = tag.replace(/^\s+|\s+$/g, ""); // remove whitespace start and end
if (res != null) tag = res;
res = tag.replace(/ +/g, "."); // replace spaces with a dot
if (res != null) tag = res;
params[1] = sortField+tag;
var list = document.createElement("ul");
list.setAttribute('class', 'xList');
list.setAttribute('tag', tag);
list.setAttribute('sortfield', sortField);
place.appendChild(list);
if(this[type].prompt) {
createTiddlyElement(list,"li",null,"listTitle",this[type].prompt);
}
var results;
if(this[type].handler) {
// console.log('params: ', params)
results = this[type].handler(params);
}
var li;
for(var t = 0; t < results.length; t++) {
li = document.createElement("li");
li.setAttribute('id', typeof results[t] == "string" ? results[t] : results[t].title);
list.appendChild(li);
createTiddlyLink(li,typeof results[t] == "string" ? results[t] : results[t].title,true);
}
};
/*}}}*/
|''Name:''|[[NeUIemTheme03]]|
|''Description:''|Changes the right sidebar|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspot.com]]|
|''Gen.Description:''|Handcrafted by @pmario|
|''PageTemplate:''|NeUIemTheme##PageTemplate|
|''ViewTemplate:''|NeUIemTheme##ViewTemplate|
|''EditTemplate:''|NeUIemTheme##EditTemplate|
|''RevisionTemplate:''|NeUIemTheme##RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
!StyleSheet
/*{{{*/
[[NeUIemTheme##StyleSheet]]
#sidebarTabs .tabset{
float: right;
width: 1em;
padding: 0;
}
#sidebarTabs .tabset:hover{
width: auto;
}
#sidebarTabs .tabset .tab{
overflow: hidden;
display: block;
}
/*}}}*/
/***
|''Name''|TiddlySpaceFollowingSuggestions|
|''Version''|0.2.5dev|
|''Description''|Provides a following macro|
|''Author''|Jon Robson|
|''Requires''|TiddlySpaceFollowingPlugin|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
!Code
***/
//{{{
(function($) {
var tweb = config.extensions.tiddlyweb;
var tiddlyspace = config.extensions.tiddlyspace;
var followMacro = config.macros.followTiddlers;
var followSuggestions = config.macros.followSuggestions = {
cache: {},
handler: function(place, macroName, params) {
// to do - limit results
place = $('<div class="suggestions" />').appendTo(place)[0];
var currentSpace = tiddlyspace.currentSpace.name;
var user = params[0] || currentSpace;
var pleaseWait = $("<div class='loading' />").text("please wait..").appendTo(place);
tweb.getUserInfo(function(activeUser) {
if(activeUser.name != tiddlyspace.currentSpace.name) {
pleaseWait.hide();
return;
}
followMacro.getFollowers(function(users) {
// suggestions are followers of people that you follow that you don't follow
var bags = followMacro._getFollowerBags(users);
var _bags = [];
for(var i = 0; i < bags.length; i++) {
_bags.push("bag:%0".format([bags[i]]));
}
var bagString = _bags.join(" OR ");
ajaxReq({
beforeSend: followMacro.beforeSend,
url: "/search?q=(%0)&select=title:!%1&select=title:!@%1".format([bagString, activeUser.name]),
dataType: "json",
success: function(tiddlers) {
pleaseWait.hide();
var suggestions = [];
for(var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
if(tiddler.tags.contains("follow")) {
var title = tiddler.title;
if(title.indexOf("@") === 0) {
title = title.substr(1);
}
if(!users.contains(title)) {
suggestions.pushUnique(title);
}
}
}
$(place).append("<div>suggestions:</div>");
var suggestionArea = $("<div class='suggestionArea' />").appendTo(place)[0];
var id = "more_%0".format([Math.random()]);
var more = $("<div class='moreButton' />").text("more...").appendTo(place).attr("id", id);
followSuggestions.cache[id] = suggestions;
var limit = suggestions.length;
more.click(function(ev) {
var suggestions = config.macros.followSuggestions.cache[id];
var newSuggestions = followSuggestions.suggest(place, suggestions, limit);
config.macros.followSuggestions.cache[id] = newSuggestions;
});
followSuggestions.suggest(place, suggestions, limit);
}
});
}, user);
});
},
randomize: function(a, b) {
if(Math.random() < Math.random()) {
return -1;
} else {
return 1;
}
},
suggest: function(place, suggestions, limit) {
var currentSpace = tiddlyspace.currentSpace.name;
suggestions = suggestions.sort(followSuggestions.randomize);
var suggestionsArea = $(".suggestionArea", place)[0];
if(suggestions.length === 0) {
$("<span />").text("no suggestions..").appendTo(suggestionsArea);
return;
}
limit = limit < suggestions.length ? limit : suggestions.length;
for(var j = 0; j < limit; j++) {
var link = $("<span />").appendTo(suggestionsArea)[0];
var title = suggestions[j];
var newTiddler = '@%0 <<newTiddler title:"@%0" fields:"server.workspace:bags/%1_public" tag:follow label:"follow">>\n'.format([title, currentSpace]);
wikify(newTiddler, link);
}
var newSuggestions = suggestions.slice(limit, suggestions.length);
var more = $(".moreButton", place);
if(newSuggestions.length == 0) {
more.remove();
}
return newSuggestions;
}
};
})(jQuery);
//}}}
|''Name:''|[[NeUIemTheme01]]|
|''Description:''|Changes the right sidebar|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspot.com]]|
|''Gen.Description:''|Handcrafted by @pmario|
|''PageTemplate:''|NeUIemTheme##PageTemplate|
|''ViewTemplate:''|NeUIemTheme##ViewTemplate|
|''EditTemplate:''|NeUIemTheme##EditTemplate|
|''RevisionTemplate:''|NeUIemTheme##RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
!StyleSheet
/*{{{*/
[[NeUIemTheme##StyleSheet]]
#sidebarTabs .tabset{
float: left;
width: 1em;
padding: 0;
}
#sidebarTabs .tabset:hover{
width: auto;
}
#sidebarTabs .tabset .tab{
overflow: hidden;
display: block;
}
/*}}}*/
!Suggestions for TiddlyWiki Repo Directory Structure
* Everything below is work in progress.
* But it seems to work and
* It should be easy, to convert existing contributors repos.
!!My directory structure
{{{
GIT_BASEDIR = /my/drive/Git .. My git base directory. Since there are different repos.
TW_TRUNKDIR = $GIT_BASEDIR/tiddly .. use TW_TRUNKDIR to make conversion easier.
$GIT_BASEDIR/tiddly/~core .. directory symlink to tiddlywiki
$TW_TRUNKDIR/tiddlywiki .. ~core .. if not there use tiddlywiki instead.
full:
/my/drive/Git/tiddly/tiddlywiki ..
contributor general structure:
$TW_TRUNKDIR/<contributor>/<vertical> ...
eg:
$TW_TRUNKDIR/tiddlyspace .. tiddlyspace is a contributor
$TW_TRUNKDIR/fnd .. git repos from fnd
$TW_TRUNKDIR/pmario .. my own git repos
$TW_TRUNKDIR/pmario/tiddlywiki .. If ~core points to it. It should be easy testing.
$TW_TRUNKDIR/pmario/tw.FancyBoxPlugin
$TW_TRUNKDIR/pmario/tw.roundabout
...
}}}
* It seems that the above should work fine, even with existing recipes from SVN repo.
* For existing contributors, there should be not too much trouble to convert it.
!!!!ToDo
* make better vertical naming conventions.
!!Environment Variables needed
see .bahsrc below
!Existing documentation
There is not much about cook and ginsu
*http://tiddlywiki.org/wiki/Dev:Cook
*{{{$TW_TRUNKDIR/core/...}}}
{{{
$ mkdir tiddlywiki
$ cd tiddlywiki
$ svn co http://svn.tiddlywiki.org/Trunk/
$ cd Trunk
$ export TW_TRUNKDIR=$PWD
$ PATH=$PATH:$TW_TRUNKDIR/tools/cooker/bash
$ cd contributors/PaulDowney/plugins/FadingMessagesPlugin
$ cook
$ open index.html
}}}
!!Cook
* Cook repo should be cloned to {{{TW_TRUNKDIR/tools/}}} directory
* Full path: {{{TW_TRUNKDIR/tools/cooker}}}
** See .bashrc for more
!.bashrc
* TW trunc directory is hardcoded in {{{/home/<userName>/.bashrc}}} file
* At the end of the file.
** According to your linux distribution there may be a lot of stuff...
{{{
# MP tiddlywiki
export TW_TRUNKDIR=/my/drive/Git/tiddly
export PATH=$PATH:$TW_TRUNKDIR/tools/cooker/bash
}}}
!!Ricipes Relative Path's
Since I have different git repos, that I want to work with. I need a Git base directory. In my case it is hardcoded.
{{{
GIT base directory /my/drive/Git/
}}}
Some {{{index.html.recipes}}} use
{{{
../../../../core
easier:
$TW_TRUNKDIR/core/...
}}}
~core = tiddlywiki ... can be a symlink, which makes it easy to point to an oter tiddlywiki dir, without changing anything.
!!Cook help info
{{{
~$ ruby -C $TW_TRUNKDIR/tools/cooker cook.rb --help
Cook Version: 1.1.10001 (Revision)
Usage: cook.rb recipename [...] [options]
Specific options:
-r, --root ROOT Root path
-c, --compress COMPRESS Compress javascript, use -c, -cr, -cy or -crp
-C, --cplugins CPLUGINS Compress javascript plugins, use -C, -Cr, -Cy or -Crp
-D, --deprecated DEPRECATED Compress deprecated javascript, use -D, -Dr or -Drp
-H, --[no-]HEAD Compress jshead, use -H
-d, --dest DESTINATION Destination directory
-o, --outputfile OUTPUTFILE Output file
-f, --format FORMAT Tiddler format
-j, --javascriptonly Generate a file that only contains the javascript
-k, --keepallcomments Keep all javascript comments
-i, --[no-]ignorecopy Ingnore copy command in recipes
-q, --[no-]quiet Quiet mode, do not output file names
-s, --[no-]stripcommets Strip comments
-t, --time Time modified from file system
-h, --help Show this message
-v, --version Show version
}}}
* ToDo: More info needed
!!Ginsu help info
{{{
~$ ruby -C $TW_TRUNKDIR/tools/cooker ginsu.rb --help
Ginsu Version: 1.1.0 (Revision)
Usage: ginsu.rb tiddlywikiname [...] [options]
Specific options:
-d, --dest DESTINATION Destination directory
-q, --[no-]quiet Quiet mode, do not output file names
-s, --[no-]subdirectories Split tidders into subdirectories by type
-t, --tag TAGDIRECTORY Split tidders into subdirectories by type
-c, --charset CHARSET Character set of filesystem.
-h, --help Show this message
--version Show version
}}}
* ToDo: More info needed
!Some suggestions?
|''Name:''|[[NeUIemTheme04]]|
|''Description:''|Play with the toolbar visibility|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspot.com]]|
|''Gen.Description:''|Automatically generated from: tsNeUIemProject|
|''PageTemplate:''|NeUIemTheme##PageTemplate|
|''ViewTemplate:''|NeUIemTheme##ViewTemplate|
|''EditTemplate:''|NeUIemTheme##EditTemplate|
|''RevisionTemplate:''|NeUIemTheme##RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
|''Init:''|NeUIemTheme04##Init|
!StyleSheet
/*{{{*/
[[NeUIemTheme03##StyleSheet]]
/* Play with the toolbar visibility */
.toolbar {
visibility: hidden;
/* opacity: 0.2; */
}
.selected .toolbar {
visibility: visible;
/* opacity: 1; */
}
/*}}}*/
/***
|''Name:''|FollowTiddlersButtonPlugin|
|''Description:''|Wraps followTiddlers macro into a button, which needs to be clicked to activate it.|
|''Author:''|Mario Pietsch|
|''Source:''||
|''Version:''|0.1.0|
|''Status:''|beta|
|''Date:''|2010.12.06|
|''Requires:''|TiddlySpaceFollowingPlugin|
|''License:''|BSD|
|''~CoreVersion:''||
Click the [?] button, to get {{{<<followTiddlers>>}}} macro activated.
!!!!Use
<<<
{{{
<<followTiddlersButton>> instead of <<followTiddlers>>
}}}
<<<
!!!!ViewTemplate
<<<
{{{
<div class='followPlaceHolder' macro='followTiddlersButton'>
<span macro="view title replyLink"></span>
</div>
}}}
<<<
***/
/*{{{*/
version.extensions.TiddlySpaceHacks = {major: 0, minor: 1, revision: 0, date: new Date(2010,12,06)};
(function ($) {
var ftb;
config.macros.followTiddlersButton = ftb = {
// should be done for easy localisation
locale: {
lblButton: '?',
txtButton: 'Find other spaces, that contain a tiddler with the same title',
},
handler: function(place, macroName, params, wikifier, paramString, tiddler){
if (!config.macros.followTiddlers) return false;
var btn = null;
// createTiddlyButton(parent, text, tooltip, action, className, id, accessKey, attribs)
btn = createTiddlyButton(place, ftb.locale.lblButton, ftb.locale.txtButton, ftb.onClick, 'followButton');
// passing all arguments to the function
$(btn).data('data', arguments);
},
onClick: function() {
var a = $(this).data("data");
if (a) {
config.macros.followTiddlers.handler.apply(config.macros.followTiddlers, a);
$(this).remove();
}
return false;
}
}; // end of hello world
}) (jQuery);
/*}}}*/
see: [[cdent plate]]@pmario
<!--{{{-->
<div class='toolbar'
macro='toolbar [[ToolbarCommands::ViewToolbar]] icons:yes height:16 width:16 more:popup'>
</div>
<div class='heading'>
<span class='spaceSiteIcon'
macro='tiddlerOrigin label:no spaceLink:yes height:48 width:48 preserveAspectRatio:yes'>
</span>
<span class="titleBar">
<div class='title' macro='view title text'></div>
<span class="subtitle" macro='viewRevisions page:5'>
last modified on
<span macro="view modified date"></span>
</span>
<div macro="view title replyLink"></div>
</span>
<span class='followPlaceHolder' macro='followTiddlers'></span>
<span class='modifierIcon'
macro='view modifier SiteIcon label:no spaceLink:yes height:48 width:48 preserveAspectRatio:yes'>
</span>
<div class='tagClear'></div>
</div>
<div class='content'>
<div class='viewer' macro='view text wikified'></div>
</div>
<div class='tagInfo'>
<div class='tidTags' macro='tags'></div>
<div class='tagging' macro='tagging'></div>
</div>
<!--}}}-->
/***
|Name|GotoPlugin|
|Source|http://www.TiddlyTools.com/#GotoPlugin|
|Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
|Version|1.9.2|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|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 displayed, pressing //escape// clears the current input.
!!!Documentation
>see [[GotoPluginInfo]]
!!!Configuration
<<<
*Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input. //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
*To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
//{{{
config.macros.gotoTiddler.listMaxSize=10; // change this number
//}}}
<<<
!!!Revisions
<<<
2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
|please see [[GotoPluginInfo]] for additional revision details|
2006.05.05 [0.0.0] started
<<<
!!!Code
***/
//{{{
version.extensions.GotoPlugin= {major: 1, minor: 9, revision: 2, date: new Date(2009,5,22)};
// automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");
if (config.options.txtIncrementalSearchMin===undefined) config.options.txtIncrementalSearchMin=3;
config.macros.gotoTiddler= {
listMaxSize: 10,
listHeading: 'Found %0 matching title%1...',
searchItem: "Search for '%0'...",
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
var quiet =params.contains("quiet");
var showlist =params.contains("showlist");
var search =params.contains("search");
params = paramString.parseParams("anon",null,true,false,false);
var instyle =getParam(params,"inputstyle","");
var liststyle =getParam(params,"liststyle","");
var filter =getParam(params,"filter","");
var html=this.html;
var keyevent=window.event?"onkeydown":"onkeypress"; // IE event fixup for ESC handling
html=html.replace(/%keyevent%/g,keyevent);
html=html.replace(/%search%/g,search);
html=html.replace(/%quiet%/g,quiet);
html=html.replace(/%showlist%/g,showlist);
html=html.replace(/%display%/g,showlist?'block':'none');
html=html.replace(/%position%/g,showlist?'static':'absolute');
html=html.replace(/%instyle%/g,instyle);
html=html.replace(/%liststyle%/g,liststyle);
html=html.replace(/%filter%/g,filter);
if (config.browser.isIE) html=this.IEtableFixup.format([html]);
var span=createTiddlyElement(place,'span');
span.innerHTML=html; var form=span.getElementsByTagName("form")[0];
if (showlist) this.fillList(form.list,'',filter,search,0);
},
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 title text... ENTER=goto, SHIFT-ENTER=search for text, DOWN=select from list"\
onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list,%search%,%showlist%);"\
onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,%quiet%,%search%,%showlist%);">\
<select name=list style="display:%display%;position:%position%;%liststyle%"\
onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
onblur="this.style.display=%showlist%?\'block\':\'none\';"\
%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler,%showlist%);"\
onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this,%showlist%);">\
</select><input name="filter" type="hidden" value="%filter%">\
</form>',
IEtableFixup:
"<table style='width:100%;display:inline;padding:0;margin:0;border:0;'>\
<tr style='padding:0;margin:0;border:0;'><td style='padding:0;margin:0;border:0;'>\
%0</td></tr></table>",
getItems:
function(list,val,filter) {
if (!list.cache || !list.cache.length || val.length<=config.options.txtIncrementalSearchMin) {
// starting new search, fetch and cache list of tiddlers/shadows/tags
list.cache=new Array();
if (filter.length) {
var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
var tiddlers=store.sortTiddlers(fn.apply(store,[filter]),'title');
} else
var tiddlers=store.reverseLookup('tags','excludeLists');
for(var t=0; t<tiddlers.length; t++) list.cache.push(tiddlers[t].title);
if (!filter.length) {
for (var t in config.shadowTiddlers) list.cache.pushUnique(t);
var tags=store.getTags();
for(var t=0; t<tags.length; t++) list.cache.pushUnique(tags[t][0]);
}
}
var found = [];
var match=val.toLowerCase();
for(var i=0; i<list.cache.length; i++)
if (list.cache[i].toLowerCase().indexOf(match)!=-1) found.push(list.cache[i]);
return found;
},
getItemSuffix:
function(t) {
if (store.tiddlerExists(t)) return ""; // tiddler
if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
return " (tag)"; // tag
},
fillList:
function(list,val,filter,search,key) {
if (list.style.display=="none") return; // not visible... do nothing!
var indent='\xa0\xa0\xa0';
var found = this.getItems(list,val,filter); // find matching items...
found.sort(); // alpha by title
while (list.length > 0) list.options[0]=null; // clear list
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++) list.options[list.length]=
new Option(indent+found[t]+this.getItemSuffix(found[t]),found[t],false,false);
if (search)
list.options[list.length]=new Option(this.searchItem.format([val]),"*",false,false);
list.size=(list.length<this.listMaxSize?list.length:this.listMaxSize); // resize list...
list.selectedIndex=key==38?list.length-1:key==40?1:0;
},
keyProcessed:
function(ev) { // utility function
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,search,showlist) {
if (event.keyCode==27) {
if (showlist) { // clear input, reset list
here.value=here.defaultValue;
this.fillList(list,'',here.form.filter.value,search,0);
}
else if (list.style.display=="none") // clear input
here.value=here.defaultValue;
else list.style.display="none"; // hide list
return this.keyProcessed(event);
}
return true; // key bubbles up
},
inputKeyHandler:
function(event,here,quiet,search,showlist) {
var key=event.keyCode;
var list=here.form.list;
var filter=here.form.filter;
// non-printing chars bubble up, except for a few:
if (key<48) switch(key) {
// backspace=8, enter=13, space=32, up=38, down=40, delete=46
case 8: case 13: case 32: case 38: case 40: case 46: break; default: return true;
}
// blank input... if down/enter... fall through (list all)... else, and hide or reset list
if (!here.value.length && !(key==40 || key==13)) {
if (showlist) this.fillList(here.form.list,'',here.form.filter.value,search,0);
else list.style.display="none";
return this.keyProcessed(event);
}
// hide list if quiet, or below input minimum (and not showlist)
list.style.display=(!showlist&&(quiet||here.value.length<config.options.txtIncrementalSearchMin))?'none':'block';
// non-blank input... enter=show/create tiddler, SHIFT-enter=search for text
if (key==13 && here.value.length) return this.processItem(event.shiftKey?'*':here.value,here,list,showlist);
// up or down key, or enter with blank input... shows and moves to list...
if (key==38 || key==40 || key==13) { list.style.display="block"; list.focus(); }
this.fillList(list,here.value,filter.value,search,key);
return true; // key bubbles up
},
selectKeyHandler:
function(event,list,editfield,showlist) {
if (event.keyCode==27) // escape... hide list, move to edit field
{ editfield.focus(); list.style.display=showlist?'block':'none'; return this.keyProcessed(event); }
if (event.keyCode==13 && list.value.length) // enter... view selected item
{ this.processItem(list.value,editfield,list,showlist); return this.keyProcessed(event); }
return true; // key bubbles up
},
processItem:
function(title,here,list,showlist) {
if (!title.length) return;
list.style.display=showlist?'block':'none';
if (title=="*") { story.search(here.value); return false; } // do full-text search
if (!showlist) here.value=title;
story.displayTiddler(null,title); // show selected tiddler
return false;
}
}
//}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onclick="if(jQuery) jQuery(document).trigger('cSaveChanges', {elem:this, comp:{menue:1}})" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})" title="Save all tiddlers to the web">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0,-1,1,0,0,0)" width="22" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<g id="iconSymbol" stroke-linejoin="round" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4" fill="none" class="showSY">
<path d="m27.73,61.043,3.2374,1.8989-1.9264,0,0,3.2808-2.8131,0,0-3.2808-1.7352,0,3.2374-1.8989z" stroke-width="1.3"/>
<g transform="matrix(1.0777574,0.08745459,-0.09502165,0.99192987,39.787119,-3.5323126)" fill="none">
<path d="m-8.7109,55.478,8.1326-1.4778,0.13409,8.5172" stroke-width="1.3"/>
<path d="m-8.623,55.846-1.7958,9.5134" stroke-width="1.5"/>
<path d="M-30.522,13.653-13.966,26.834" transform="matrix(0.8,0,0,0.8,13,43)" stroke-width="2"/>
<path d="m-32.798,31.699,17.733-19.616" transform="matrix(0.8,0,0,0.8,13,43)" stroke-width="2"/>
</g>
</g>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
{{noBullets{<<xList xCase "sort." "." "[tag[mainMenu]]">>}}}
----
<<tiddler [[Temporary SideBySide##Code50]]>> <<tiddler [[Temporary SideBySide##Code33]]>> <<tiddler [[Temporary SideBySide##Code100]]>>
[[License]]
~~<<version>>~~
/***
!EmasticPercent
***/
/*{{{*/
.dp5, .dp10,.dp15,.dp20,.dp25,.dp30,.dp33,.dp35,.dp40,.dp45,.dp50,
.dp55,.dp60,.dp65,.dp67,.dp70,.dp75,.dp80,.dp85,.dp90,.dp95,.dp100
{float:left; display: inline; }
.dp5{width:5%;}
.dp10{width:10%;*width:9.9%;} .dp15{width:15%;*width:14.9%;} .dp20 {width:20%;*width:19.9%;}
.dp25{width:25%;*width:24.9%;} .dp30{width:30%;*width:29.9%;} .dp33 {width:33.33%;*width:33.3%;}
.dp35{width:35%;*width:34.9%;} .dp40{width:40%;*width:39.9%;} .dp45 {width:45%;*width:44.9%;}
.dp50{width:50%;*width:49.9%;} .dp55{width:55%;*width:54.9%;} .dp60 {width:60%;*width:59.9%;}
.dp65{width:65%;*width:64.9%;} .dp67{width:66.67%;*width:66.6%;} .dp70 {width:70%;*width:69.9%;}
.dp75{width:75%;*width:74.9%;} .dp80{width:80%;*width:79.9%;} .dp85 {width:85%;*width:84.9%;}
.dp90{width:90%;*width:89.9%;} .dp95{width:95%;*width:94.9%;} .dp100{width:100%;*width:99.9%;}
/*}}}*/
/***
!EmasticGrid
***/
/*{{{*/
.main { width:70em;margin:0 auto;text-align:left; }
.clear {clear:both;}
.dl1,.dl2,.dl5,.dl10,.dl15,.dl20,.dl25,.dl30,.dl35,.dl40,.dl45,.dl50,.dl55,.dl60,.dl65,.dl70,.dl75
{float:left; display: inline; }
.dr1,.dr2,.dr5,.dr10,.dr15,.dr20,.dr25,.dr30,.dr35,.dr40,.dr45,.dr50,.dr55,.dr60,.dr65,.dr70,.dr75
{float:right; display: inline; }
.dl1, .dr1 {width:1em;} .dl2, .dr2 {width:2em;} .dl5, .dr5 {width:5em;}
.dl10, .dr10{width:10em;} .dl15, .dr15{width:15em;} .dl20, .dr20{width:20em;}
.dl25, .dr25{width:25em;} .dl30, .dr30{width:30em;} .dl35, .dr35{width:35em;}
.dl40, .dr40{width:40em;} .dl45, .dr45{width:45em;} .dl50, .dr50{width:50em;}
.dl55, .dr55{width:55em;} .dl60, .dr60{width:60em;} .dl65, .dr65{width:65em;}
.dl70, .dr70{width:70em;} .dl75, .dr75{width:75em;}
.ml1 {margin-left:1em;} .ml2 {margin-left:2em;} .ml3 {margin-left:3em;} .ml4 {margin-left:4em;}
.ml5 {margin-left:5em;} .ml10{margin-left:10em;} .ml15{margin-left:15em;}
.ml20{margin-left:20em;} .ml25{margin-left:25em;} .ml30{margin-left:30em;}
.ml35{margin-left:35em;} .ml40{margin-left:40em;} .ml45{margin-left:45em;}
.ml50{margin-left:50em;} .ml55{margin-left:55em;} .ml60{margin-left:60em;}
.ml65{margin-left:65em;} .ml70{margin-left:70em;} .ml75{margin-left:75em;}
.mr5 {margin-right:5em;} .mr10{margin-right:10em;} .mr15{margin-right:15em;}
.mr20{margin-right:20em;} .mr25{margin-right:25em;} .mr30{margin-right:30em;}
.mr35{margin-right:35em;} .mr40{margin-right:40em;} .mr45{margin-right:45em;}
.mr50{margin-right:50em;} .mr55{margin-right:55em;} .mr60{margin-right:60em;}
.mr65{margin-right:65em;} .mr70{margin-right:70em;} .mr75{margin-right:75em;}
.mt1{margin-top:1em;} .mt2{margin-top:2em;} .mt3{margin-top:3em;} .mt4{margin-top:4em;}
.mt5{margin-top:5em;} .mt10{margin-top:10em;}
.mt20{margin-top:20em;} .mt30{margin-top:30em;} .mt40{margin-top:40em;}
.mt50{margin-top:50em;}
.fluid {width:auto; float:none;}
.hp{width:100%; float:left; }
.clearfix, .main{ display:block;}
.clearfix:after, .main:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
/* IE5/MAC hack \*/
* html .clearfix{ display: inline; height: 1px;}
/* close */
/*}}}*/
/***
!EmasticAbsolut
***/
/*{{{*/
.main{position:relative;}
.lf0,.lf5,.lf10,.lf15,.lf20,.lf25,.lf30,.lf35,.lf40,.lf45,.lf50,.lf55,.lf60,.lf65,.lf70,.lf75,.lf80,.lf85,.lfn5,.lfn10,.lfn15,.lfn20,.lfn25,.lfn30,
.tp0,.tp5,.tp10,.tp15,.tp20,.tp25,.tp30,.tp35,.tp40,.tp45,.tp50,
.bt0,.bt5,.bt10,.bt15,.bt20,.bt25,.bt30,.bt35,.bt40,.bt45,.bt50,
.rtn5,.rtn10,.rtn20,.rtn30{position:absolute;}
.lf0{left:0em;} .lf5{left:5em;} .lf10{left:10em;} .lf15{left:15em;} .lf20{left:20em;}
.lf25{left:25em;} .lf30{left:30em;} .lf35{left:35em;} .lf40{left:40em;} .lf45{left:45em;}
.lf50{left:50em;} .lf55{left:55em;} .lf60{left:60em;} .lf65{left:65em;} .lf70{left:70em;}
.lf75{left:75em;} .lf80{left:80em;} .lf85{left:85em;} .lfn5{left:-5em;} .lfn10{left:-10em;}
.lfn15{left:-15em;} .lfn20{left:-20em;} .lfn25{left:-25em;} .lfn30{left:-30em;}
.rtn5 {right:-5em;} .rtn10{right:-10em;} .rtn15{right:-15em;} .rtn20{right:-20em;}
.rtn25{right:-25em;} .rtn30{right:-30em;}
.tp0 {top:0em;} .tp5{top:5em;} .tp10{top:10em;} .tp15{top:15em;} .tp20{top:20em;} .tp25{top:25em;}
.tp30{top:30em;} .tp35{top:35em;} .tp40{top:40em;} .tp45{top:45em;} .tp50{top:50em;}
.bt0{bottom:0em;} .bt5{bottom:0em;} .bt10{bottom:10em;} .bt15{bottom:15em;} .bt20{bottom:20em;}
.bt25{bottom:25em;} .bt30{bottom:30em;} .bt35{bottom:35em;} .bt40{bottom:40em;} .bt45{bottom:45em;}
.bt50{bottom:50em;}
.zi1{ z-index:1;} .zi2{ z-index:2;} .zi3{ z-index:3;} .zi4{ z-index:4;} .zi5{ z-index:5;}
/*}}}*/
/***
!EmasticGadgets
***/
/*{{{*/
/* CSS Document */
.rc {-moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; border:1px solid #fff; }
.fr {border:1px solid #ccc; padding:0.25em;}
.byline {
font-family: "Lucida Grande", Tahoma;
font-size: 0.865em;
font-weight: lighter;
font-variant: normal;
text-transform: uppercase;
color: #666666;
letter-spacing: 0.4em;
display: block;
margin-bottom: 1.734em;
padding:0em 0em 0em 1em;
}
.and {font-family: Baskerville, "Goudy Old Style", "Palatino", "Book Antiqua", serif;
font-style: italic;
color: #777;
}
.tc {text-align:center;}
.tr {text-align:right;}
.tl {text-align:left;}
.b {font-weight:bold;}
.pl1{padding-left:1em;}
.pl2{padding-left:2em;}
.pl3{padding-left:3em;}
.ppl2{padding-left:1.8%;}
.ppl3{padding-left:3.13%;}
.ppl5{padding-left:4.8%;}
.water{color:#5582d1;}
.earth{color:#4e3e2c;}
.air{color:#f1fff7;}
.fire{ color:#ff8a19;}
/* drinks food */
.wine{color:#4a040a;}
.beer{color:#F0C030;}
.caffe{color:#473523;}
.caffe-cream{color:#b68d3d;}
.espresso{color:#2c1901;}
.caramel{color:#ab671f;}
.chocolate{color:#290200;}
.black-pepper{color:#444334;}
.pepper-lite{color:#8d8a72;}
.lipstick{color:#c20c0c;}
.oldbook{font-family:"Book Antiqua","Warnock Pro","Goudy Old Style","Palatino",Georgia,serif;}
.note{font-family:Georgia, "Times New Roman", Times, serif; font-style:italic; font-size:0.9em; margin:0.1em; color:#333;}
.mono{font-family:"Courier New", Courier, monospace;}
/*}}}*/
/***
!EmasticFreeStyle
***/
/*{{{*/
.dpfr{float:right;}
/*}}}*/
in reply to bengillies [[tiddler titles vs. unique IDs]]@bengillies:
<<<
>@fnd said:
>[[Tweet|http://cdent.tumblr.com/post/1350976279/bye-bye-facebook-hello-tiddlyspace]] [[names|dfbc17918d2442479a2fcb35f1e0aa8a]] are not >supposed to show up for end-users; they're just identifiers rather than human-readable names.
>(cf. @chris-dent's [[blog post|http://cdent.tumblr.com/post/1350976279/bye-bye-facebook-hello-tiddlyspace]])
I think the point that @pmario is making (and a concern that I share), is that using a UUID is not very meaningful and that, when something pops up in my activity stream I see it with a UUID, which makes the whole thing fairly useless, until the point I click on it (if I actually do click on it).
<<<
Yes and no.
I am not very happy with UUIDs in the activity stream. If I'd reply to some of them, it would be ok to find them again. But if there are more, you'll need a full text search to get the right tiddler title.
On the other hand, I did have a similar problem, that I described at TiddlyWebDatabase@pmario. So I'd be happy, if someone makes an abstraction layer + tools needed to really work with it :)
@fnd said:
<<<
The issue of unique IDs was also discussed during the original design of TiddlyWeb, and it was decided that human-friendly names are central to the tiddler paradigm (in part because it makes linking easy, not requiring any layers of indirection).
<<<
Good to know, and was there a "plan B"?
!Others say
<<tsScan [[tiddler titles vs. unique IDs]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
<<tiddler [[Groupie##Create your own GroupieNews]]>>
----
Have a look at Groupie@pmario to learn more.
<<tiddler TEMPLATES##follow>>
in reply to [[plugin meta markup for tiddlywiki]]@jon
<<<
Update: @pmario [[in his response|plugin meta markup for tiddlywiki]]@pmario stated "plugin code should not be dependent on its comments." - although I agree with this opinion, this is not the case in many existing TiddlyWiki plugins and seems to have become something of a "TiddlyWiki standard".
<<<
I wouldn't name it "TiddlyWiki standard". I think it is "hacky". I can't beleve, that there isn't a better way, than rely on comments.
<<<
Note stylesheets activated in this way can however be overwritten by shadow tiddlers or additional plugins, it simply delivers the stylesheet in an easy to maintain way (note maintaining css in javascript is very tiresome and messy).
<<<
For a newbie user, it just isn't easy to maintain, if it means, that you have to mess with a "core" plugin code. Even if you "only" change the comment section. It also makes propper updating a plugin much more difficult. If not to say impossible.
If a user overwrites the shadow tiddler, and messes up the CSS, s/he only needs to delete the tiddler and the shadow tiddler will be reactivated by the plugin. Updating won't break a user CSS.
If the user messes up the "core" code, it creates an issue, that could have been avoided, by the developer.
IMO there is no problem, that maintaining JS-CSS code is more complicated for a developer. Since it doesn't change very often in production. Alpha and beta can work with a section CSS but production shouldn't!
Creating a new "comments parser" like ({{{/*!** -- ***/}}}) IMO is fighting the symptoms, not solving a problem.
----
in reply to [[plugin meta markup for tiddlywiki]]@jon
* I think, the only way, how advanced plugins should access/activate there ~StyleSheets is the following.
* The user, doesn't need to "hack" the plugin code to change someting.
//{{{
config.shadowTiddlers["StyleSheetMyPlugin"]="/*{{{*/\n"+
".myClass {\n"+
" font-size: 0.9em;\n"+
"}\n"+
"/*}}}*/";
store.addNotification("StyleSheetMyPlugin",refreshStyles);
//}}}
* If a plugin needs some default values, they should be initialized with an object and can be overwritten with named params.
* IMO plugin code should not be dependent on its comments.
/***
|''Name''|ShowDown|
|''Description''|Allows to use MarkDown syntax in a tiddler|
|''Documentation''|http://tobibeer.tiddlyspace.com/#ShowDown|
|''Author''|Tobias Beer|
|''Contributions''|Mario Pietsch, Paul Downey|
|''Version''|0.9.1|
|''Requires''|https://raw.github.com/tobibeer/TiddlyWikiPlugins/master/resources/ShowDown/ShowDown.js|
|''Source''|https://raw.github.com/tobibeer/TiddlyWikiPlugins/master/plugins/ShowDown.js|
|''License''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion''|2.5.3|
|''Type''|plugin|
!Installation
Install ShowDown.js first and tag it <<tag systemConfig>>.
!Code
***/
//{{{
config.formatters.push({
name: "showdown",
match: "ยงยงยง",
lookaheadRegExp: /\s?ยงยงยง((?:.|\n)*?)ยงยงยง\s?/mg,
handler: function (w) {
var match, t;
this.lookaheadRegExp.lastIndex = w.matchStart;
match = this.lookaheadRegExp.exec(w.source);
if (match && match.index == w.matchStart) {
t = (new Showdown.converter()).makeHtml(match[1]);
wikify(
'<html>' + t + '</html>',
createTiddlyElement(w.output, 'div', null, 'showdown')
)
w.nextMatch = match.index + match[0].length;
}
}
})
//}}}
* A very minimalistic presentation mode is possible.
* Which keeps the focus of the audience at the basics.
* But powerfull editing can be activated, which creates a WOW
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
/%
!info
|Name|ToggleLeftSidebarEm|
|Source|http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki#ToggleLeftSidebarEm|
|Version|0.1.0|
|Author|Mario Pietsch|
|Derived from:|http://www.tiddlytools.com/#ToggleLeftSidebar|
|License|http://creativecommons.org/licenses/by-nc-sa/3.0/at/|
|~CoreVersion|2.6|
|Type|transclusion|
|Description|show/hide left sidebar (MainMenu) for FreeStyle Themes. Works only with EmasticSystem|
Usage
<<<
{{{
<<tiddler ToggleLeftSidebarEm>>
<<tiddler ToggleLeftSidebarEm with: label tooltip>>
<<tiddler ToggleLeftSidebarEm with: {{config.options.chkShowLeftSidebar?'โ':'โบ'}}>>
}}}
Try it: <<tiddler ToggleLeftSidebarEm##show
with: {{config.options.chkShowLeftSidebar?'โ':'โบ'}}>>
<<<
Configuration:
<<<
{{{
config.options.chkShowLeftSidebar (true)
config.options.txtToggleLeftSideBarLabelShow (โบ)
config.options.txtToggleLeftSideBarLabelHide (โ)
}}}
<<<
!end
!show
<<tiddler {{
var co=config.options;
if (co.chkShowLeftSidebar===undefined) co.chkShowLeftSidebar=true;
getDP = function(name) {
var width = undefined;
var myregexp = /dp([\d]{1,3})/;
var elem = jQuery(name);
var text = elem.attr('class');
var match = myregexp.exec(text);
if (match != null) {
width = match[1];
} else {
elem = jQuery(name).parent();
text = elem.attr('class');
match = myregexp.exec(text);
if (match != null) {
width = match[1]
}
else elem = undefined;
}
return {'width': width, 'elem': elem};
}; // end function
setDP = function(cmd, elem, target) {
if (!elem || !target) return alert('elem or target undefined!');
var newWidth = 0;
if (cmd === 'hide' && (elem.elem.css('display') != 'none')) {
newWidth = parseInt(target.width) + parseInt(elem.width);
jQuery(elem.elem).hide();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
}; // end function
var mm = getDP('#mainMenu');
var da = getDP('#displayArea');
var sb = getDP('#sidebar');
var cmd = co.chkShowLeftSidebar?'show':'hide';
setDP(cmd, mm, da);
'';}}>><html><nowiki><a href='javascript:;' title="$2"
onmouseover="
this.href='javascript:void(eval(decodeURIComponent(%22(function(){try{('
+encodeURIComponent(encodeURIComponent(this.onclick))
+')()}catch(e){alert(e.description?e.description:e.toString())}})()%22)))';"
onclick="
var co=config.options;
var opt='chkShowLeftSidebar';
var show=co[opt]=!co[opt];
getDP = function(name) {
var width = undefined;
var myregexp = /dp([\d]{1,3})/;
var elem = jQuery(name);
var text = elem.attr('class');
var match = myregexp.exec(text);
if (match != null) {
width = match[1];
} else {
elem = jQuery(name).parent();
text = elem.attr('class');
match = myregexp.exec(text);
if (match != null) {
width = match[1]
}
else elem = undefined;
}
return {'width': width, 'elem': elem};
}; // end function
setDP = function(cmd, elem, target) {
if (!elem || !target) return alert('elem or target undefined!');
var newWidth = 0;
if (cmd === 'hide') {
newWidth = parseInt(target.width) + parseInt(elem.width);
jQuery(elem.elem).hide();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
else if (cmd === 'show') {
newWidth = parseInt(target.width) - parseInt(elem.width);
jQuery(elem.elem).show();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
}; // end function
var mm = getDP('#mainMenu');
var da = getDP('#displayArea');
var sb = getDP('#sidebar');
var cmd = co.chkShowLeftSidebar?'show':'hide';
setDP(cmd, mm, da);
saveOptionCookie(opt);
var labelShow=co.txtToggleLeftSideBarLabelShow||'►';
var labelHide=co.txtToggleLeftSideBarLabelHide||'◄';
if (this.innerHTML==labelShow||this.innerHTML==labelHide)
this.innerHTML=show?labelHide:labelShow;
this.title=(show?'hide':'show')+' left sidebar';
var sm=document.getElementById('storyMenu');
if (sm) config.refreshers.content(sm);
return false;
">$1</a></html>
!end
%/<<tiddler {{
var src='ToggleLeftSidebarEm';
src+(tiddler&&tiddler.title==src?'##info':'##show');
}} with: {{
var co=config.options;
var labelShow=co.txtToggleLeftSideBarLabelShow||'►';
var labelHide=co.txtToggleLeftSideBarLabelHide||'◄';
'$1'!='$'+'1'?'$1':(co.chkShowLeftSidebar?labelHide:labelShow);
}} {{
var tip=(config.options.chkShowLeftSidebar?'hide':'show')+' left sidebar';
'$2'!='$'+'2'?'$2':tip;
}}>>
/***
|''Name''|SvgEvent_Info|
|''Description''|connects .svg mouse events with global TW jQuery custom events.|
|''Author''|Mario Pietsch|
|''Version''|0.2.0|
|''Source''|http://fxplugins.tiddlyspace.com|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.6|
|''Keywords''|svg, events, animation, commands|
!Idea
http://softwareas.com/automagic-event-registration
!The plugin structure
# [[SvgEvent_Animations]] .. animation componets
# [[SvgEvent_Menue]] .. menue / toolbar command components
!Needed inside an .svg tiddler
*eg: [[tfgNewTiddler.svg]]
*onclick(): {{{onclick="jQuery(document).trigger('cmd3', {elem:this, comp:{menue:1}})"}}}
**Click the icon, will trigger cmd3 in SvgEvent_Menue
*onmousedown: {{{onmousedown="jQuery(document).trigger('cmd4', {elem:this, comp:{animations:1}})"}}}
*onmouseup: {{{onmouseup="jQuery(document).trigger('cmd3', {elem:this, comp:{animations:1}})"}}}
**onmousedown, onmouseup are activating the corresponding commands in SvgEvent_Animations
!Known issues
!Elements tagged {{{fxPlugins}}}
<<list filter [tag[fxPlugins]]>>
/***
|''Name''|TiddlySpaceRevisionView|
|''Description''|Show tiddler revisions in a stack of cards view|
|''Author''|BenGillies|
|''Version''|0.2.0|
|''Status''|beta|
|''Source''|http://github.com/TiddlySpace/tiddlyspace|
|''CodeRepository''|http://github.com/TiddlySpace/tiddlyspace|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.6.0|
|''Requires''|TiddlyWebAdaptor|
!Usage
The viewRevisions macro can be attached to any element, which should be passed
in as a parameter.
For example:
<<viewRevisions page:10 link:"<<view modified date>>">>
would show the revisions "stack of cards" view, 10 at a time, when the modified
date is clicked.
!Code
***/
//{{{
(function($) {
var me = config.macros.viewRevisions = {
revisionTemplate: "RevisionTemplate",
revSuffix: " [rev. #%0]", // text to append to each tiddler title
defaultPageSize: 5, // default number of revisions to show
defaultLinkText: "View Revisions", // when there's nothing else to use
offsetTop: 30, // in px
offsetLeft: 10, // in px
shiftDownDelay: 50, // in ms
visibleSlideAmount: 20, // amount of revisions to show on left hand edge after sliding
zIndex: 100, // default z-index
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
params = paramString.parseParams(null, null, true)[0];
var tiddlerElem = story.findContainingTiddler(place);
var revButton;
var pageSize = parseInt(params.page[0], 10) || me.defaultPageSize;
var linkObj = params.link ? params.link[0] || me.defaultLinkText : false;
if(linkObj) {
revButton = $('<span class="button openRevisions" />')
.appendTo(place);
wikify(linkObj, revButton[0], null, tiddler);
} else {
revButton = place;
}
$(revButton).click(function() {
if (!$(tiddlerElem).hasClass("revisions")) {
me.showRevisions(tiddlerElem, tiddler, pageSize);
} else {
me.closeRevisions(tiddlerElem);
}
});
},
// initialisation for revision view
showRevisions: function(tiddlerElem, tiddler, pageSize) {
var context = {
host: tiddler.fields["server.host"],
workspace: tiddler.fields["server.workspace"]
};
$(tiddlerElem).addClass("revisions").attr("revName", tiddler.title);
// ensure toolbar commands deactivate RevisionsView
$("a", ".toolbar", tiddlerElem).each(function(index, btn) {
var _onclick = btn.onclick;
btn.onclick = function(e) {
me.closeRevisions(tiddlerElem);
_onclick.apply(this, arguments);
};
});
// ensure default action deactivates RevisionsView
var _ondblclick = tiddlerElem.ondblclick;
tiddlerElem.ondblclick = function(e) {
me.closeRevisions(tiddlerElem);
_ondblclick.apply(this, arguments);
};
var type = tiddler.fields["server.type"];
var adaptor = new config.adaptors[type]();
var userParams = {
tiddlerElem: tiddlerElem,
pageSize: pageSize,
title: tiddler.title
};
me.createCloak(tiddlerElem);
adaptor.getTiddlerRevisionList(tiddler.title, null, context, userParams,
function(context, userParams) {
// strip the current revision
context.revisions.shift();
me.expandStack(context, userParams);
});
},
// fetch the actual revision and put it in the tiddler div
showRevision: function(place, revision, callback) {
var context = {
host: revision.fields["server.host"],
workspace: revision.fields["server.workspace"]
};
var userParams = {
revElem: place
};
var type = revision.fields["server.type"];
var adaptor = new config.adaptors[type]();
var revNo = revision.fields["server.page.revision"];
adaptor.getTiddlerRevision(revision.title, revNo, context, userParams,
function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title += me.revSuffix
.format([$(place).attr("revision")]);
tiddler.fields.doNotSave = true;
if (store.getTiddler(tiddler.title)) {
store.deleteTiddler(tiddler.title);
}
store.addTiddler(tiddler);
//now, populate the existing div
var revElem = userParams.revElem;
$(revElem).attr("id", story.tiddlerId(tiddler.title));
$(revElem).attr("refresh", "tiddler");
var getTemplate = function() {
var themeName = config.options.txtTheme;
if (themeName) {
return store.getTiddlerSlice(themeName,
me.revisionTemplate) || me.revisionTemplate ||
"ViewTemplate";
} else {
return (store.getTiddler(me.revisionTemplate)) ?
me.revisionTemplate : "ViewTemplate";
}
};
var template = getTemplate();
story.refreshTiddler(tiddler.title, template, true);
callback(tiddler);
});
},
createCloak: function(promoteElem) {
var el = $(promoteElem);
// cache styles for resetting later
el.data({
top: el.css("top"),
left: el.css("left"),
zIndex: el.css("z-index")
});
$('<div class="revisionCloak" />').css("z-index", me.zIndex)
.click(function() {
me.closeRevisions(promoteElem);
})
.appendTo(document.body);
el.css("z-index", me.zIndex + 1);
},
// clean up, removing all evidence of revision view
closeRevisions: function(promoteElem) {
var el = $(promoteElem);
// revert the original tiddler back to its previous state
el.removeAttr("revName").removeClass("revisions").css({
top: el.data("top"),
left: el.data("left"),
zIndex: el.data("zIndex")
});
// remove any revisions still in the store
var revisions = $(".revisions");
revisions.each(function(index, revision) {
var revAttributes = revision.attributes;
if ((revAttributes.revname) &&
(revAttributes.revision)) {
var revName = revAttributes.revname.value;
var revNo = revAttributes.revision.value;
var title = revName + me.revSuffix.format([revNo]);
if (store.getTiddler(title)) {
store.deleteTiddler(title);
}
}
});
// delete the previous revisions
revisions.remove();
// remove the cloak
$(".revisionCloak").remove();
},
// calback from getting list of revisions
expandStack: function(context, userParams) {
var pageSize = userParams.pageSize;
var from = userParams.from || 0;
var tiddlerElem = userParams.tiddlerElem;
userParams.defaultHeight = $(tiddlerElem).height();
userParams.defaultWidth = $(tiddlerElem).width();
if (from < context.revisions.length) {
me.displayNextRevision(tiddlerElem, userParams, context, from,
from + pageSize - 1);
}
},
// place the next div above and behind the previous one
displayNextRevision: function(tiddlerElem, userParams, context, from, to) {
var revision = context.revisions[from];
var callback = function() {
var revText = revBtn.getRevisionText(tiddlerElem, revision);
tiddlerElem = me.createRevisionObject(tiddlerElem, context,
userParams, revText);
$(tiddlerElem)
.attr("revision", (context.revisions.length - from));
if ((from < to) && ((from + 1) < context.revisions.length)){
me.displayNextRevision(tiddlerElem, userParams, context,
from + 1, to);
} else if ((context.revisions.length - 1) > to) {
me.showMoreButton(tiddlerElem, context, userParams, to + 1);
}
};
me.shiftVisibleDown(userParams.title, callback);
},
createRevisionObject: function(tiddlerElem, context, userParams, text) {
var newPosition = me.calculatePosition(tiddlerElem, context);
return $('<div class="revisions tiddler" />')
.css({
position: "absolute",
top: newPosition.top,
left: newPosition.left,
"z-index": me.zIndex + 1,
height: userParams.defaultHeight,
width: userParams.defaultWidth
})
.attr("revName", userParams.title)
.append(text)
.insertBefore(tiddlerElem);
},
// move the already present revisions down by 1 to fit the next one in
shiftVisibleDown: function(title, callback) {
var revisions = $("[revName='%0'].revisions".format([title]));
var revisionCount = revisions.length;
$(revisions).animate({top: "+=" + me.offsetTop},
me.shiftDownDelay, function() {
revisionCount -= 1;
if ((callback) && (!revisionCount)) {
callback();
}
});
},
// where we put the new revision
calculatePosition: function(elem, context) {
var offset = $(elem).offset();
var currentPosition = $(elem).position();
var newPosition = {
top: currentPosition.top - me.offsetTop
};
if ((context.restrictLeft) ||
((offset.left - me.offsetLeft) <
$("#contentWrapper").offset().left)) {
newPosition.left = $(elem).position().left;
context.restrictLeft = true;
} else {
newPosition.left = currentPosition.left - me.offsetLeft;
}
return newPosition;
},
// equivalent of displayNextRevision, but for the more button
showMoreButton: function(tiddlerElem, context, userParams, moreIndex) {
userParams.from = moreIndex + 1;
me.shiftVisibleDown(userParams.title, function() {
var btn = me.createRevisionObject(tiddlerElem, context, userParams,
"");
var more = createTiddlyButton(btn[0], "more...", "show more revisions",
function() {
if ($(".viewRevision").length) {
return;
}
userParams.tiddlerElem = btn[0];
$(btn).text("")
.append(revBtn
.getRevisionText(btn[0], context.revisions[moreIndex]))
.attr("revision", context.revisions.length - moreIndex);
me.expandStack(context, userParams);
});
$(more).css("float", "right");
});
},
stripRevFromTitle: function(revisionTitle) {
return revisionTitle.split(/ ?\[rev\. #[0-9]+\]$/)[0];
},
onClickRevision: function(revElem, revision, callback) {
// don't do anything if we are still loading
if ($(".revisions").hasClass("loading")) {
return null;
}
var origTitle = me.stripRevFromTitle(revision.title);
if ($(revElem).hasClass("viewRevision")) {
$(".revisions").addClass("loading");
me.slideIn(revElem, revision, origTitle, function() {
store.deleteTiddler(revision.title);
revision.title = origTitle;
$(revElem).text("").append(revBtn.getRevisionText(revElem,
revision))
.removeAttr("tags").removeAttr("tiddler")
.removeAttr("refresh").removeAttr("template")
.removeAttr("id");
$(".revisions").removeClass("loading");
if (callback) {
callback();
}
});
$(revElem).removeAttr("prevPos").removeClass("viewRevision");
} else {
var viewRevision = function() {
var prevPos = $(revElem).position().left;
$(revElem).addClass("viewRevision").attr("prevPos", prevPos);
$(".revisions").addClass("loading");
me.showRevision(revElem, revision, function(rev) {
me.slideOut(revElem, rev, origTitle, function() {
$(".revisions").removeClass("loading");
});
});
};
// make sure another revision isn't already out
if ($(".viewRevision").length) {
var newRevElem = $(".viewRevision")[0];
var newRevision = store.getTiddler($(newRevElem)
.attr("tiddler"));
me.onClickRevision(newRevElem, newRevision, viewRevision);
} else {
viewRevision();
}
}
},
slideOut: function(revElem, revision, title, callback) {
var leftMostPos = $("[revName='%0'].revisions".format([title]))
.offset().left;
var width = $(revElem).width();
var originalLeftPos = $(story.getTiddler(title))
.position().left;
var slideAmount = leftMostPos + width - me.visibleSlideAmount;
$("[revName='%0'].revisions:not(.viewRevision)".format([title]))
.animate({left: "-=" + slideAmount}, 1000);
$(revElem)
.attr("baseHeight", $(revElem).css("height"))
.css("height", "auto")
.animate({left: originalLeftPos}, 1000, callback);
},
slideIn: function(revElem, revision, title, callback) {
var slideAmount = $(revElem).offset().left -
$(story.getTiddler(title)).offset().left;
var origRevPos = $(revElem).attr("prevPos");
$("[revName='%0'].revisions:not(.viewRevision)".format([title]))
.animate({left: "+=" + slideAmount}, 1000);
$(revElem).animate({left: origRevPos}, 1000, function() {
$(revElem)
.css("height", $(revElem).attr("baseHeight"))
.removeAttr("baseHeight");
callback();
});
}
};
var revBtn;
config.macros.slideRevision = revBtn = {
btnText: "created by %0 at %1 on %2",
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var btn = revBtn.getRevisionText(place, tiddler);
$(place).append(btn);
},
getRevisionText: function(place, revision) {
var text = revBtn.btnText.format([revision.modifier,
revision.modified.formatString("0hh:0mm"),
revision.modified.formatString("0DD MMM YYYY")]);
var btn = $('<a href="javascript:;" class="button revButton" />')
.text(text)
.click(function() {
var revElem = story.findContainingTiddler(this);
me.onClickRevision(revElem, revision);
});
return btn;
}
};
})(jQuery);
//}}}
<<tiddler FollowTemplate>>
in reply to @jon:
<<<
This can be done using import from uri. An FAQ question would suffice for the time being to explain this properly. Any extra needs will be turned into new stories.
<<<
I don't think, that it should be a simple copy. Some times it should be a move. So it needs to be deleted (or moved to archive) at the source space. If you only have several tiddlers, that are moved you may remember, which tiddlers need to be deleted in the source space. But try this with serveral 100 tiddlers.
<<tiddler FollowTemplate>>
<<activity supress:spaceSiteIcon supress:userSiteIcon >>
<<tiddler FollowTemplate>>
<<tiddler FollowTemplate>>
<<tiddler FollowTemplate>>
! Thoughts About TS Communication
~RePlanadu@cdent contains some interesting ideas.
><<slider chkRePlanado "RePlanadu@cdent" "click to see the full post: RePlanadu@cdent" "open RePlanadu@cdent">>
----
>In a TiddlyWiki presented by TiddlySpace, the following bubble (the little speech bubble with a number in it) is an indicator of replies. Opening the bubble shows links that can be followed to read the replies.
Technically, there exist 2 components (plugins) at the moment, that create the little number in the "following bubble".
#The first one is {{{followTiddlers}}}, which searches for the exact same tiddler title, at all existing spaces. But the number shown and links presented is filtered. The filter limits the results to those spaces, the user follows. eg http://tiddlyspace.com/search?q=title:%22Test%22 will create about 14 hits. But if you don't follow any of those users you'll get no results.
#The second one is {{{linkedTiddlers}}}. It displays backlinks, where the text content contains eg: {{{test@pmario}}}. This plugin gives me a very limited view but it is a precise one. Since I know, these tiddlers link back to my text. eg: http://pmario.tiddlyspace.com/bags/pmario_public/tiddlers/test/backlinks, creates an empty list, because none of those tiddlers actuall link to my tiddler.
''Since the "following bubble" doesn't show all informations, most users don't know, that there may be some interesting content out there.''
<<<
I can imagine another useful interface: a two-up display. On the left, the current user's tiddler A, on the right a scrolling display of all replies to that tiddler:
{{{
+----------+---------+
| | |
| | reply 1 |
| | |
| A |---------|
| | |
| | reply 2 |
| | |
| |---------|
+----------+---------+
}}}
<<<
As chris stated, authors A may use reply 1 or/and reply 2 to enhance there understanding. But this is also true for author B. So if reply 1 isn't a reply but it's own independent but influenced / linked viewpoint, in my opinion a possibility for metacommunication is missing. Mixing thins up, is the way it is used at the moment. But imo this is not very convenient.
I like this ASCII art and I want to extend it a bit.
{{{
+-----------+-----------+
/ / /|
/ history / / |
/ of A / / |
/ / / |
+-----------+-----------+ |
| | B | |
-------> | back | | <---------- talk about
talk about A | link <---- link | | talk about B <--- B talk
---------- | | | | ------------ ----------
---------- | |-----------| | ------------ ----------
---------- | A | C | + ------------ ----------
---------- | | | / ------------ ----------
---------- | link ----> back | /
| | link | /
| |-----------|/
+-----------+-----------+
}}}
For me it turns out, that most of the time I'm interested in the first version of topic A. If tiddlers are reviewed, by there authors, from time to time, they pop up in my activity stream. But now I'm only interested in the changes. So ''"What's new" and "How it comes"''.
That's why I'm trying to bring the "talk about" component into the game. It should help to spepareate the metacommunication from the "topic" tiddler content. see: @chat space. If used, it may help, to answere the question: ''"How it comes"'', if the discussion is permanently stored.
A related topic: [[The Sync mechanism and april1111]]@pmario
----
As a user, I want to have 2 modes:
!!!first mode: "just do it"
a) Everything edited offline should be tranfered to the server, if possible.
b) Everything, that is newer at the server, and I haven't touched it at the client, update the client.
c) Tell me, what was successful
d) Tell me what went wrong with:
d.1) If something at a) was not possible = conflict, tell me and let me decide
d.2) If something at b) was not possible, tell me and let me decide
!!!second mode: "firt tell me"
e) Simulate "just do it" and tell me what will happen.
e.1) optional) If I push button - "just do it" go on with a)
f) Tell me what will went wrong (like d)
f.1) Let me decide
g) "just do it" with predefined decisions
----
It looks like the new functions can handle this very well.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#FF4646" offset="0"/>
<stop id="stop2" stop-color="#ffcccc" offset="0.66462"/>
<stop id="stop3" stop-color="#FF4646" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" style="stroke-dasharray:none;" transform="translate(0.0627706, -0.0627706)" stroke="#4d4d4d" stroke-linecap="butt" stroke-miterlimit="4" stroke-width="1.60000002" fill="none">
<path id="path2874" style="stroke-dasharray:none;" d="m21.748,51.452,1.7934,14.247,7.9706,0,2.4908-15.144-12.255,0.89669z"/>
<path id="path2880" style="stroke-dasharray:none;" d="m25.435,51.452,0.84687,14.048"/>
<path id="path2882" style="stroke-dasharray:none;" d="M30.068,51.104,28.573,65.351"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
/***
|''Name:''|XCaseListPlugin|
|''Description:''|Adds a new command ''xCase'' to the core list macro|
|''Author:''|Mario Pietsch|
|''Version:''|0.3|
|''Date:''|2010.08.03|
|''Status:''|''beta''|
|''Source:''|http://apm-plugins.tiddlyspot.com/#XCaseListPlugin|
|''License''|[[MIT License]]|
|''CoreVersion:''|2.5.0|
|''Requires:''||
|''Documentation:''|this file|
|''Keywords:''|list, sort, not case sensitive, filter|
!Description
This plugin performs a alphabetical sort for tiddlers. Default it is not case sensitive. That means ab = AB = aB = Ab! And it does some little more filtering using the RegExp syntax. The RegExp Syntax can be a little bit tricky to read and configure. But the best description I have found is at [[regular-expressions.info]]
!!!Example
{{{
<<list xCase title '[m]'>>
}}}
< <list xCase title '[m]'>>
!Default Format
{{{
<<list xCase>>
}}}
!More Possibilities
<<<
!!!Reverse sort order
{{{
<<list xCase -title >>
}}}
!!!Some basic filtering
*Every tiddler title, that starts with a number from 0 to 9.
{{{
<<list xCase title '[0-9]'>>
}}}
*Every tiddler title, that starts with an ''"a"'' or ''"b"'' or ''"c"''.
{{{
<<list xCase title '[abc]'>>
}}}
*Every tiddler title, that starts with exactly ''abc''.
{{{
<<list xCase title 'abc'>>
}}}
<<<
!!!Some advanced filtering
<<<
*same as above but with a tagList for additional filtering.
*adding the tag filter will disable the "excludeLists" setting !!
**If you need excludeLists, than you have to define it with the expression.
*XCaseListPlugin should be compatible to [[MatchTagsPlugin]] from TiddlyTools!
{{{
<<list xCase title '[a]' "[tag[MyTag]]">>
}}}
!!!Global / Local Settings
|<<option chkXCaseListCaseSensitive>> Global sort case sensitive |Sets case sensitiv sort globally|
|<<option chkXCaseListCheckField>> Sortfield defines case sensitive |Ignores global setting. Evaluates sortField and sets the value everytime <br> {{{<<list xCase sortField ..>>}}} is executed.|
If sortField is eg: 'title' .. not case sensitive (default).
if sortField is eg: 'Title' or 'TITLE' .. case sesitive sort is active.
<<<
!Code
***/
/*{{{*/
if(!version.extensions.XCaseListPlugin) { //# ensure that the plugin is only installed once
version.extensions.XCaseListPlugin = { installed: true };
config.macros.list.xCase = {};
config.macros.list.xCase.handler = function(params){
var lookupField = 'tags';
var lookupValue = 'excludeLists';
var lookupMatch = false;
var sortField = params[1] || '+title';
// global setting for case sensitive search
var caseSensitive = config.options.chkXCaseListCaseSensitive || false;
var chkSortField = config.options.chkXCaseListCheckField || false;
// if this option is active the macro parameter sortField is parsed
// global setting is ignored !!
if (chkSortField) caseSensitive = (sortField != sortField.toLowerCase());
sortField = sortField.toLowerCase();
// check if numberedText called this macro.
// this parameter is used by <<list numberedText ..>> macro
// if you directly use it, it will return an unsorted list !!!
var numberedText = false;
if (sortField.substr(0, 1)== '#') {
numberedText = true;
sortField = sortField.substr(1);
caseSensitive = false;
}
// check for ascending or descending sort order
var asc = 1;
switch (sortField.substr(0, 1)) {
case "-":
asc = -1;
case "+":
sortField = sortField.substr(1);
break;
default: ;
}
var results = [];
var tmpResults = [];
// set the default for regExp filtering
var regSnip = params[2] || '.';
var regExp = new RegExp('^' + regSnip, 'im');
var match = null;
// check if [tag[...]] is set
var tagList = params[3] || '';
var tagMatch = tagList.length != 0; // if list is empty everything is valid.
if (tagMatch) {
tmpResults = store.filterTiddlers(params[3]);
for (var i=0, max=tmpResults.length; i<max; i++){
// match = tmpResults[i][sortField].match(regExp);
match = tmpResults[i].title.match(regExp);
if (match) results.push(tmpResults[i]);
}; // for ..
}
else {
store.forEachTiddler(function(title, tiddler){
var f = !lookupMatch;
for (var lookup = 0; lookup < tiddler[lookupField].length; lookup++) {
if (tiddler[lookupField][lookup] == lookupValue) {
f = lookupMatch;
}
}; // for..
if (f) {
// match = tiddler[sortField].match(regExp);
match = tiddler.title.match(regExp);
if (match) results.push(tiddler);
}; // if (f) ..
}); // store.forEach ..
}; // else ..
if (TiddlyWiki.isStandardField(sortField)) {
if (caseSensitive) {
results.sort(function(a, b){
return a[sortField] < b[sortField] ? -asc : a[sortField] == b[sortField] ? 0 : asc;
}); // results.sort
}
else if (numberedText) {
// do nothing, return the list, for further processing !
}
else {
results.sort(function(a, b){
return a[sortField].toLowerCase() < b[sortField].toLowerCase() ? -asc : a[sortField].toLowerCase() == b[sortField].toLowerCase() ? 0 : asc;
}); // results.sort
}; // if
}
else {
results.sort(function (a, b) {
var aField = (a.fields[sortField]) ? a.fields[sortField] : 'zzz';
var bField = (b.fields[sortField]) ? b.fields[sortField] : 'zzz';
return aField.toLowerCase() < bField.toLowerCase() ? -asc : aField.toLowerCase() == bField.toLowerCase() ? 0 : +asc;
});
}
return results;
}
} //# end of "install only once"
/*}}}*/
{{dp50{
!!! @pmario
<<tsScan url:"/search?q=tag:@pmario _limit:100" template:"SearchTemplate" sort:-modified>>
}}}{{dp50{
!!! @developers
<<tsScan url:"/search?q=tag:@developers _limit:100" template:"SearchTemplate" sort:-modified>>
}}}
----
You need to include the space named @following, that it works.
/%
< <tsScan @pmario searchField:"tag" template:"SearchTemplate" sort:-modified query:"select=modified:>28d">>
%/
/***
|''Name''|TiddlyWebConfig|
|''Description''|configuration settings for TiddlyWebWiki|
|''Author''|FND|
|''Version''|1.3.2|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/TiddlyWebConfig.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Requires''|TiddlyWebAdaptor ServerSideSavingPlugin|
|''Keywords''|serverSide TiddlyWeb|
!Code
***/
//{{{
(function($) {
if(!config.extensions.ServerSideSavingPlugin) {
throw "Missing dependency: ServerSideSavingPlugin";
}
if(!config.adaptors.tiddlyweb) {
throw "Missing dependency: TiddlyWebAdaptor";
}
if(window.location.protocol != "file:") {
config.options.chkAutoSave = true;
}
var adaptor = tiddler.getAdaptor();
var recipe = tiddler.fields["server.recipe"];
var workspace = recipe ? "recipes/" + recipe : "bags/common";
var plugin = config.extensions.tiddlyweb = {
host: tiddler.fields["server.host"].replace(/\/$/, ""),
username: null,
status: {},
getStatus: null, // assigned later
getUserInfo: function(callback) {
this.getStatus(function(status) {
callback({
name: plugin.username,
anon: plugin.username ? plugin.username == "GUEST" : true
});
});
},
hasPermission: function(type, tiddler) {
var perms = tiddler.fields["server.permissions"];
if(perms) {
return perms.split(", ").contains(type);
} else {
return true;
}
}
};
config.defaultCustomFields = {
"server.type": tiddler.getServerType(),
"server.host": plugin.host,
"server.workspace": workspace
};
// modify toolbar commands
config.shadowTiddlers.ToolbarCommands = config.shadowTiddlers.ToolbarCommands.
replace("syncing ", "revisions syncing ");
config.commands.saveTiddler.isEnabled = function(tiddler) {
return plugin.hasPermission("write", tiddler) && !tiddler.isReadOnly();
};
config.commands.deleteTiddler.isEnabled = function(tiddler) {
return !readOnly && plugin.hasPermission("delete", tiddler);
};
// hijack option macro to disable username editing
var _optionMacro = config.macros.option.handler;
config.macros.option.handler = function(place, macroName, params, wikifier,
paramString) {
if(params[0] == "txtUserName") {
params[0] = "options." + params[0];
var self = this;
var args = arguments;
args[0] = $("<span />").appendTo(place)[0];
plugin.getUserInfo(function(user) {
config.macros.message.handler.apply(self, args);
});
} else {
_optionMacro.apply(this, arguments);
}
};
// hijack isReadOnly to take into account permissions and content type
var _isReadOnly = Tiddler.prototype.isReadOnly;
Tiddler.prototype.isReadOnly = function() {
return _isReadOnly.apply(this, arguments) ||
!plugin.hasPermission("write", this);
};
var getStatus = function(callback) {
if(plugin.status.version) {
callback(plugin.status);
} else {
var self = getStatus;
if(self.pending) {
if(callback) {
self.queue.push(callback);
}
} else {
self.pending = true;
self.queue = callback ? [callback] : [];
var _callback = function(context, userParams) {
var status = context.serverStatus || {};
for(var key in status) {
if(key == "username") {
plugin.username = status[key];
config.macros.option.propagateOption("txtUserName",
"value", plugin.username, "input");
} else {
plugin.status[key] = status[key];
}
}
for(var i = 0; i < self.queue.length; i++) {
self.queue[i](plugin.status);
}
delete self.queue;
delete self.pending;
};
adaptor.getStatus({ host: plugin.host }, null, _callback);
}
}
};
(plugin.getStatus = getStatus)(); // XXX: hacky (arcane combo of assignment plus execution)
})(jQuery);
//}}}
<<tiddler FollowTemplate>>
FND in 13d25210495@FND
>I still can't get over how bad the new Google Groups interface is
I couldn't agree more. The old one wasn't perfect but the focus was on the content. Now the focus is on the interface and it is distracting.
That's me. Have a look at my Projects@pmario
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onclick="if(jQuery) jQuery(document).trigger('cNewTiddler', {elem:this, comp:{menue:1}})" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})" title="Create a new tiddler">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0,-1,1,0,0,0)" width="22" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<g id="iconSymbol" stroke-linejoin="miter" transform="translate(0.17754196,0)" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4" stroke-dasharray="none" fill="none" class="showSY">
<path d="m21.585,50.448,7.3934-0.000001,0,4.5527,4.3752,0,0,10.101-11.769,0z" stroke-width="1.6"/>
<path d="m29.712,50.447,3.644,3.8077" stroke-width="1.60000002"/>
</g>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
!Mario Pietsch 2009-2011
<html>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/at/"><img alt="Creative Commons Lizenzvertrag" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png" /></a><br />Where not explicitly stated, this <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/InteractiveResource" rel="dc:type">Space / Content </span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/at/">Attribution-NonCommercial-ShareAlike 3.0 Austria </a>.
</html>
<<tiddler FollowTemplate>>
In reply to [[SideBarOptions in the Backstage]]@jon
* At the moment I don't want to use the backstage as a user interface. For me it is the tweaking area, if I damaged my space.
* Mooooost of the time I keep it closed.
* But I like the new layout with the menues at the left and the icons on the right. I vote +1 for this :)
* Creating a new space should be as easy as using {{{<<install>>}}} from @space-install
** Or even better. It should be that easy as with http://pen.io http://pmario.pen.io
*** It's simplicity is gorgeous. It's functionality is hmmm :(
*** A TiddlySpace start page like this and then, if users are asking for more, tell them. I think this would be a killer.
<<tiddler FollowTemplate>>
@@Please do not modify this tiddler; it was created automatically upon space creation.@@
/***
|''Name''|AddNowCommand|
|''Description''|Opens a tiddler in edit mode and adds "Date and Time" at the end of the text.|
|''Authors''|see Related to|
|''Version''|0.0.3|
|''Date''|2011-06-10|
|''Status''|@@beta@@|
|''Source''|http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki#AddNowCommand|
|''License''|BSD|
|''CoreVersion''|2.5|
|''Related to''|http://groups.google.com/group/tiddlywiki/browse_thread/thread/9f3fb012e80fdc4|
|''Keywords''|toolbar command add date time edit|
!!!Description
<<<
To use this new toolbar command you have to add {{{addNow}}} to ToolbarCommands tiddler
eg:
{{{
|~ViewToolbar|tagSearch addNow +editTiddler ...
}}}
<<<
!!!Date Format
<<<
Possible date formats can be seen at [[TiddlyWiki.org|http://tiddlywiki.org/#%5b%5bDate%20Formats%5d%5d]]
To change the date format add the following line to a tiddler eg: [[zzConfig]] tagged systemConfig
//{{{
config.commands.addNow.dateFormat = 'YYYY-0MM-0DD 0hh:0mm';
//}}}
To change the insert {{{mode}}} add:
//{{{
config.commands.addNow.mode = 'post';
//}}}
To change the {{{selectedText}}} in mode = 'pre' add:
//{{{
config.commands.addNow.selectedText = 'your text here';
//}}}
<<<
!!!Code
***/
//{{{
// http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area/841121#841121
// $('#elem').selectRange(3,5);
jQuery.fn.selectRange = function(start, end) {
return this.each(function() {
if (this.setSelectionRange) {
this.focus();
this.setSelectionRange(start, end);
} else if (this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
});
};
config.commands.addNow = {
text: "addNow",
tooltip: "Edit tiddler and add [Date & Time]!",
selectedText: "insert text",
mode: 'pre', // 'pre' or 'post'
spacingText: '\n\n----\n',
insertText: '[%0]\n',
dateFormat: 'YYYY-0MM-0DD 0hh:0mm',
isEnabled: function(tiddler) {
return (!readOnly && !tiddler.isTagged('systemConfig'));
}
};
config.commands.addNow.handler = function(event,src,title)
{
config.commands.editTiddler.handler.call(this,event,src,title);
var text = jQuery(story.getTiddler(title)).find('textarea[edit=text]');
var spacer = text.val() ? this.spacingText : '' ;
var dynText = this.insertText.format([new Date().formatString(this.dateFormat)]);
if (this.mode == 'post') {
text.val(text.val() + spacer + dynText);
}
else {
text.val(dynText + this.selectedText + spacer + text.val() );
jQuery(text).selectRange(dynText.length, dynText.length + this.selectedText.length);
}
return false;
};
//}}}
//{{{
/***
|''Name''|tiddlywiki.js|
|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
|''Author''|PMario|
|''Version''|0.1.7|
|''Status''|''stable''|
|''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
|''Documentation''|http://codemirror.tiddlyspace.com/|
|''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
|''CoreVersion''|2.5.0|
|''Requires''|codemirror.js|
|''Keywords''|syntax highlighting color code mirror codemirror|
! Info
CoreVersion parameter is needed for TiddlyWiki only!
***/
//{{{
CodeMirror.defineMode("tiddlywiki",function(e,t){function y(e,t,n){return t.tokenize=n,n(e,t)}function b(e,t){var n=!1,r;while((r=e.next())!=null){if(r==t&&!n)return!1;n=!n&&r=="\\"}return n}function S(e,t,n){return w=e,E=n,t}function x(e,t){var n=e.sol(),i,v;t.block=!1,i=e.peek();if(n&&/[<\/\*{}\-]/.test(i)){if(e.match(d))return t.block=!0,y(e,t,k);if(e.match(f))return S("quote","quote");if(e.match(u)||e.match(a))return S("code","code");if(e.match(l)||e.match(c)||e.match(h)||e.match(p))return S("code","code");if(e.match(o))return S("hr","hr")}i=e.next();if(n&&/[\/\*!#;:>|]/.test(i)){if(i=="!")return e.skipToEnd(),S("header","header");if(i=="*")return e.eatWhile("*"),S("list","list");if(i=="#")return e.eatWhile("#"),S("list","list");if(i==";")return e.eatWhile(";"),S("list","list");if(i==":")return e.eatWhile(":"),S("list","list");if(i==">")return e.eatWhile(">"),S("quote","quote");if(i=="|")return S("table","table")}if(i=="{"&&e.match(/\{\{/))return y(e,t,k);if(/[hf]/i.test(i)&&/[ti]/i.test(e.peek())&&e.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i))return S("link-external","link-external");if(i=='"')return S("string","string");if(i=="~")return S("text","brace");if(/[\[\]]/.test(i)&&e.peek()==i)return e.next(),S("brace","brace");if(i=="@")return e.eatWhile(s),S("link-external","link-external");if(/\d/.test(i))return e.eatWhile(/\d/),S("number","number");if(i=="/"){if(e.eat("%"))return y(e,t,N);if(e.eat("/"))return y(e,t,L)}if(i=="_"&&e.eat("_"))return y(e,t,A);if(i=="-"&&e.eat("-")){if(e.peek()!=" ")return y(e,t,O);if(e.peek()==" ")return S("text","brace")}if(i=="'"&&e.eat("'"))return y(e,t,C);if(i!="<")return S(i);if(e.eat("<"))return y(e,t,M);e.eatWhile(/[\w\$_]/);var m=e.current(),g=r.propertyIsEnumerable(m)&&r[m];return g?S(g.type,g.style,m):S("text",null,m)}function T(e){return function(t,n){return b(t,e)||(n.tokenize=x),S("string","string")}}function N(e,t){var n=!1,r;while(r=e.next()){if(r=="/"&&n){t.tokenize=x;break}n=r=="%"}return S("comment","comment")}function C(e,t){var n=!1,r;while(r=e.next()){if(r=="'"&&n){t.tokenize=x;break}n=r=="'"}return S("text","strong")}function k(e,t){var n,r=t.block;return r&&e.current()?S("code","code"):!r&&e.match(g)?(t.tokenize=x,S("code","code-inline")):r&&e.sol()&&e.match(v)?(t.tokenize=x,S("code","code")):(n=e.next(),r?S("code","code"):S("code","code-inline"))}function L(e,t){var n=!1,r;while(r=e.next()){if(r=="/"&&n){t.tokenize=x;break}n=r=="/"}return S("text","em")}function A(e,t){var n=!1,r;while(r=e.next()){if(r=="_"&&n){t.tokenize=x;break}n=r=="_"}return S("text","underlined")}function O(e,t){var n=!1,r,i;while(r=e.next()){if(r=="-"&&n){t.tokenize=x;break}n=r=="-"}return S("text","line-through")}function M(e,t){var n,r,s,o;return e.current()=="<<"?S("brace","macro"):(n=e.next(),n?n==">"&&e.peek()==">"?(e.next(),t.tokenize=x,S("brace","macro")):(e.eatWhile(/[\w\$_]/),s=e.current(),o=i.propertyIsEnumerable(s)&&i[s],o?S(o.type,o.style,s):S("macro",null,s)):(t.tokenize=x,S(n)))}var n=e.indentUnit,r=function(){function e(e){return{type:e,style:"text"}}return{}}(),i=function(){function e(e){return{type:e,style:"macro"}}return{allTags:e("allTags"),closeAll:e("closeAll"),list:e("list"),newJournal:e("newJournal"),newTiddler:e("newTiddler"),permaview:e("permaview"),saveChanges:e("saveChanges"),search:e("search"),slider:e("slider"),tabs:e("tabs"),tag:e("tag"),tagging:e("tagging"),tags:e("tags"),tiddler:e("tiddler"),timeline:e("timeline"),today:e("today"),version:e("version"),option:e("option"),"with":e("with"),filter:e("filter")}}(),s=/[\w_\-]/i,o=/^\-\-\-\-+$/,u=/^\/\*\*\*$/,a=/^\*\*\*\/$/,f=/^<<<$/,l=/^\/\/\{\{\{$/,c=/^\/\/\}\}\}$/,h=/^<!--\{\{\{-->$/,p=/^<!--\}\}\}-->$/,d=/^\{\{\{$/,v=/^\}\}\}$/,m=/\{\{\{/,g=/.*?\}\}\}/,w,E;return{startState:function(e){return{tokenize:x,indented:0,level:0}},token:function(e,t){if(e.eatSpace())return null;var n=t.tokenize(e,t);return n},electricChars:""}}),CodeMirror.defineMIME("text/x-tiddlywiki","tiddlywiki");
//}}}
<<tiddler FollowTemplate>>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#CC9900" offset="0"/>
<stop id="stop2" stop-color="#E8D18B" offset="0.66462"/>
<stop id="stop3" stop-color="#CC9900" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" style="stroke-dasharray:none;" transform="matrix(0.744603, -0.571406, 0.571406, 0.744603, -26.72, 29.8594)" stroke="#4d4d4d" stroke-width="2.4000001" fill="none">
<rect id="rect3648" style="stroke-dasharray:none;" ry="1.9242" height="6.1172" width="10.95" y="55.132" x="19.169"/>
<rect id="rect3650" style="stroke-dasharray:none;" ry="1.9242" height="6.1172" width="10.95" y="56.513" x="25.822"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
/***
|''Name:''|StoryGlueMacro|
|''Description:''|Makes SelectStoryMacro and NavigationMacro work together|
|''Author:''|Mario Pietsch|
|''Source:''|http://a-pm.tiddlyspot.com|
|''Version:''|0.5.2|
|''Status:''|beta|
|''Date:''|2010.02.06|
|''Requires:''|SelectStoryMacro, NavigationMacro|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.2|
!!!!!Usage:
<<<
Add the macro to the ViewTemplate, specifying the tag eg:"story" and a cookie: eg:"ACTIVESTORY" to navigate between the possible stories.
Find the line:
{{{
<div class='viewer' macro='view text wikified'></div>
}}}
''and add the following line below:''
{{{
<div class='viewer' macro='storyGlue story ACTIVESTORY</div>
}}}
If you are allready using "navigation" macro. Replace "navigation" macro because it is called by StoryGlueMacro to handle navigation.
Don't delete it comment it !!
<<<
!!!!!Parameter
<<<
General Format:
{{{
<div class='viewer' macro='storyGlue storyTag COOKIENAME</div>
}}}
storyTag: The macro searches all tiddlers tagged: "storyTag"
>If the tiddler is found in one or more stories. "selectStory" macro is activated instead of "navigation" macro to switch to a new story if you want.
>If it doesn't find a matching story nothing is displayed.
COOKIENAME is last part of an txtSelectStory option cookie, that storyGlue will look at.
>The cookie is used, to store the name of the actual story, that will be used for navigating.
>The cookie can be manipulated also by SelectStoryMacro if the same name is used.
>Bee carefull if you use a different name. Look at my examples!
>If you don't use SelectStoryMacro you will need a little program somewhere in your init functions.
>{{{config.options.txtSelectStoryCOOKIENAME = "yourTiddlerThatContainsAStoryAndIsTaggedWithXXXX";}}}
>Better have a look at [[zzMptwUserConfigPlugin]]
The option: {{{<<option txtSelectStoryACTIVESTORY>>}}}: ''<<varDisplay {{config.options.txtSelectStoryACTIVESTORY}}>>''
contains the active story, that is used in [[a-pm presentation manager|http://a-pm.tiddlyspot.com]].
If you click a tiddler, which is not part of the active story, but of any tiddler tagged: "story", storyGlue will activate the SelectStoryMarcro. SelectStoryMacro will display all stories found in a different color (default: blue). If you click on of the small sqares, it will activate this story, which can be used for navigatin now.
The SelectStoryMacro can also work stand alone. See [[SelectStoryMacro]] for more details.
<<<
!!!!!Attention
<<<
There is no limit using different cookie names. ''But be warned: If you get confused. It is not my fault :)''
If your cookie name is eg: MYSTORY the option which contains the active story will be: {{{<<option txtSelectStoryMYSTORY>>}}}
It is always: txtSelectStory + yourCookieName.
In viewTemplate call it with:
{{{
<div class='viewer' macro='storyGlue story MYSTORY</div>
}}}
<<<
!!!!!Example:
<<<
[[Demo|Story1]]
<<<
!!!!!Revision History
<<<
*Version: 0.5.1 - 2010.01.30
**commented the displayMessage if an empty story is selected from SelectStoryMacro
<<<
***/
/*{{{*/
//
//!BEGIN-PLUGIN-CODE
if(!version.extensions.StoryGluePlugin) { //# ensure that the plugin is only installed once
version.extensions.StoryGluePlugin = { installed: true };
if(!config.extensions) { config.extensions = {}; } //# obsolete from v2.4.2
config.macros.storyGlue= {
defineStoryMsg: "~StoryGlue: option name is not defined!\n"+
"Read the Documentation!\n" +
"Check your ~ViewTemplate!\n" +
"Check: config.options.",
handler: function(place, macroName, params, wikifier, paramString, tiddler){
if (!config.macros.navigation)
return false;
if (!config.macros.selectStory)
return false;
if (config.options.chkDisableStoryGlue== undefined)
config.options.chkDisableStoryGlue= false;
var sets = store.getTaggedTiddlers(params[0]); // get tiddlers tagged eg:'story'
var optId = config.macros.selectStory.optPreTxt + params[1]; // get the last part of the cookie name
var txtArray = [];
for (var i = 0; i < sets.length; i++) {
txtArray.push(sets[i].title);
}
var navIndex = txtArray.indexOf(config.options[optId]);
if (navIndex == -1) {
// console.log(this.defineStoryMsg+optId);
return false; // can only be if option is undefined or different pc / cookie
}
var tiddlers = store.getTiddlerText(sets[navIndex].title).readBracketedList(); // read tiddlers in active story
var tidIndex = tiddlers.indexOf(tiddler.title);
// storyline ok .. use navigation macro
if (tidIndex != -1) {
var p = "tiddlers:{{store.getTiddlerText('" + sets[navIndex].title + "').readBracketedList()}}";
invokeMacro(place, 'navigation', p, wikifier, tiddler);
return false;
}
if (config.options.chkDisableStoryGlue)
return false;
if (this.debug) console.log('not disabled:', tiddlers);
if (tidIndex == -1) {
// search other stories for this tiddler.
var text = params[1]+' '+'tiddlers: [[';
var found = false;
for (var i=0; i<txtArray.length; i++) { //!!!!!!! better search needed !
tiddlers = store.getTiddlerText(txtArray[i]).readBracketedList(); // read tiddlers in active story
tidIndex = tiddlers.indexOf(tiddler.title);
if (tidIndex != -1) {
found = true;
text = text + '"' + txtArray[i] + '" ';
} // if tidIndex ..
} // for i < txtArray.len ..
text = text+']]';
// console.log( 'text: ' + text);
// console.log( 'found: ' + found);
// var text = params[1]+" "+ "tiddlers: {{ var array = store.filterTiddlers('[tag[" + params[0] +
// "]]');var text = ''; for (var i=0; i<array.length; i++)"+
// "{text = text + '[[' + array[i].title + ']]';};}}"; // be carefull evaluated string !!!
if (found) invokeMacro(place, 'selectStory', text, wikifier, tiddler);
} // handler
} // config macro
}
} //# end of "install only once"
/*}}}*/
/*{{{*/
/* make it print a little cleaner */
/* FireFox only prints one page. Google Chrome works. */
@media print {
/* basic setting */
#displayArea {
font:11px/120% Arial, serif;
background-color: white !important;
background-image: none !important;
color:black;
width: 95%;
}
#sidebarSearch,
.clear,
.topMenu,
.quickopentag a.button,
.miniTag,
.noPrint,
.tagglyTagging {
display: none ! important;
}
/* not sure if we need all the importants */
.tiddler {
-moz-box-shadow: none;
-web-box-shadow: none;
boder:none ! important;
border-style: none ! important;
margin:0px ! important;
padding:0px ! important;
padding-bottom:2em ! important;
display:inline;
}
.headerShadow {
visibility: hidden ! important;
}
.tagglyTagged .quickopentag, .tagged .quickopentag {
/* border-style: none ! important; */
}
.siteIcon,
.spaceSiteIcon {
display: none ! important;
}
}
/*}}}*/
Learn more at: http://tiddlyspace.com
! CpHelloWorld
{{dp25{
|Name | Value |h
|Background| #f2f0e2 |
|Foreground| #1c1a0c |
|PrimaryPale| #E3DEBE |
|PrimaryLight| #d9d1a5 |
|PrimaryMid| #b3a34b |
|PrimaryDark| #553300 |
|SecondaryPale| #ffffff |
|SecondaryLight| #bda5d9 |
|SecondaryMid| #7c4bb3 |
|SecondaryDark| #29193C |
|TertiaryPale| #ffffff |
|TertiaryLight| #a5ccd9 |
|TertiaryMid| #4b9ab3 |
|TertiaryDark| #000000 |
|Error| #f88 |
}}}{{dp50{<<paletteView>>}}}
<<tiddler FollowTemplate>>
in reply to 8c01a60e057b1f938763f977048e4ba9@fnd
<<<
While I got the basic framework in place now, special cases like deletions and TiddlySpace's idea of publishing have me worried. I'll try to ignore these for the moment, to be revisited once the basic prototype is ready.
<<<
Do you want to discuss deletions? I don't uderstand, why TiddlySpace's idea of publishing is a problem.
PS:
The tiddler title is ugly.
!Others say
<<tsScan 8c01a60e057b1f938763f977048e4ba9 fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
~@ben ~@chris,
Thx for the stuff. :)
I think I basically understand the issue. It's just about page ranking at google, and may be about canonical URIs.
As a user, I really don't care, where a link comes from. As long as I don't get a 404 page. I personally don't like to click "goo.gl/wtfisthis". I like search results, that, if I click them, are loading a page. And ... it would be nice if the page contains the words that I searched for. Really.. this is important for me.
In an ideal web, if someone links to my topic. In no way this link would be broken. Even if I renamed the topic :)
I think it is cool, to get my own subdomain, if I create a tiddlyspace account. (This was mainly the reason, why I activated one :) On the other hand, for me URI means, that a resouce (tiddler) is uniquely identified. pmario.tiddlyspac.com/anyTiddler is _not_ uniqe. But most of the time, if I use google, I am not searching for a tiddler title. I am searching for the tiddler content.
So whatever google stores in there database, I don't think it is important how the link looks like. It is important that, it is allways the same and that google thinks, that the domain where it comes from is impoartant.
I am sure, we get more links and hits, at tiddlyspace.com than at pmario.tiddlyspace.com
I aloso don't remember URL's. I bookmark them, and search for tags, to find them again.
----
PS: I posted to the issue because cdent said:
>One, as you mention, is adding canonical to markupprehead. I think it would remain fair to do that just on new spaces and not worry about existing ones.
Especially ''and not worry about existing ones.'' caused my attention. So whatever you decide. I want it updated automatically at my spaces. Or I need a description, what I have to do :)
Thx for your attention!
A [[SiteIcon|SiteIcon tiddler]]@glossary helps provide some identity to your space. Ideally it'd be a square and a minimum of 48*48 pixels size. You can upload your site icon using the uploader below.
<<binaryUploadPublic title:SiteIcon>>
in reply to @jon:
<<<
!Writings
Me-and-TiddlyWiki@bauwe
!Plugins
TabScrollMacro@pmario
pmario has created an interesting way of simplifying tabs! I quite like this! It's ''a lot'' better than my TabConveyorBeltPlugin@frankenstein-plugins !
<<<
hi jon. it was @tobibeer who did the TabScrollMacro
Global news see: http://news.tiddlyspace.com
News works best if you include "following" space into your homespace!
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Account</title>
<link href="/bags/common/tiddlers/profile.css" type='text/css' rel='stylesheet' >
<link href="/bags/common/tiddlers/admin.css" type='text/css' rel='stylesheet' >
<link href="/bags/common/tiddlers/jquery-ui.custom.css" type='text/css' rel='stylesheet' >
</head>
<body>
<div id="container">
<div class="main section">
<a class="app" href="/">home</a>
<div class="left">
<div id="siteiconArea">
<h2>User Icon</h2>
<div>
<img id="siteicon" class="siteicon">
<form id="upload" method="POST" enctype="multipart/form-data">
<input type="hidden" name="title" value="SiteIcon" />
<input type="hidden" name="tags" value="excludeLists">
<input type="hidden" name="csrf_token" class="csrf" />
<input type="file" name="file" accept="image/*" />
<input type="submit" value="upload" />
</form>
<div id="dropzone">Drop file here
<img class="notloading" src="/bags/common/tiddlers/ajax-loader.gif" alt="submitting SiteIcon" />
</div>
</div>
</div>
<h2>Find Space</h2>
<form class="spaceSearch">
<input class="inputBox" type="text" placeholder="find space" />
<a href="http://docs.tiddlyspace.com/What%20is%20a%20Space%3F" class="help"
title="What is a space?">What is a space?</a>
<button>view all</button>
</form>
<div class='list-container'>
You are a member of the following spaces:
<ul class='ts-space-search'>
</ul>
</div>
<h2>Create New Space</h2>
<form class="ts-spaces">
<input class="inputBox" type="text" name="spacename" placeholder="space name"><span class="hostSuffix">.tiddlyspace.com</span>
<input type="submit" value="Create Space" />
</form>
</div>
<div class="right">
<h2>Change Password</h2>
<form class="ts-password">
<input class="inputBox" placeholder="existing password" type="password" name="password">
<input class="inputBox" placeholder="new password" type="password" name="new_password">
<input class="inputBox" placeholder="new password" type="password" name="new_password_confirm">
<input type="submit" value="Change password">
</form>
<h2>OpenID</h2>
<h3>Why OpenID?</h3>
<a href="http://openid.net/"><img src="/bags/common/tiddlers/openid.png" alt="openid" ></a><br />
Use just one username and password across hundreds of OpenID-enabled sites.<br />
It's an open standard.<br />
<a href="http://openid.net/what/">learn more</a>
<ul class="ts-identities"></ul>
<form class="ts-openid" target="_top">
<div>
Add an openid:
</div>
<input class="inputBox" type="text" name="openid" placeholder="your openid" />
<input type="submit" value="Register" />
<a href="http://openid.net/get-an-openid/" class="help"
title="What is an open id?">What is an open id?</a>
</form>
</div>
<div class="clear"></div>
</div>
</div>
<script src="/bags/common/tiddlers/backstage.js"></script>
<script src='/bags/common/tiddlers/jquery.js'></script>
<script src='/bags/tiddlyspace/tiddlers/chrjs'></script>
<script src='/bags/common/tiddlers/chrjs.space'></script>
<script src='/bags/common/tiddlers/chrjs.users'></script>
<script src='/bags/common/tiddlers/chrjs.identities'></script>
<script src="/bags/common/tiddlers/jquery-ui.custom.js"></script>
<script src='/bags/common/tiddlers/jquery-form.js'></script>
<script src="/bags/common/tiddlers/siteiconupload.js"></script>
<script src='/bags/common/tiddlers/ts.js'></script>
<script src="/status.js"></script>
<script type="text/javascript">
/*
* jQuery UI Autocomplete HTML Extension
*
* Copyright 2010, Scott Gonzรกlez (http://scottgonzalez.com)
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* http://github.com/scottgonzalez/jquery-ui-extensions
*/
(function( $ ) {
var proto = $.ui.autocomplete.prototype,
initSource = proto._initSource;
function filter( array, term ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
return $.grep( array, function(value) {
return matcher.test( $( "<div>" ).html( value.label || value.value || value ).text() );
});
}
$.extend( proto, {
_initSource: function() {
if ( this.options.html && $.isArray(this.options.source) ) {
this.source = function( request, response ) {
response( filter( this.options.source, request.term ) );
};
} else {
initSource.call( this );
}
},
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( $( "<a></a>" )[ this.options.html ? "html" : "text" ]( item.label ) )
.appendTo( ul );
}
});
})( jQuery );
/***
_accounts application specific javascript
***/
var link;
ts.init(function(ts) {
if(ts.user.anon) { // redirect to homepage when user not logged in
window.location = ts.getHost();
} else if(ts.user.name === ts.currentSpace){
initSiteIconUpload(ts.user.name);
} else {
link = $("<a />").attr("href", ts.getHost(ts.user.name) + "/_account").text("Change User Icon");
$("#siteiconArea div").empty().append(link);
}
$(".hostSuffix").text("." + ts.getHost("").split("//")[1]);
ts.getSpaces(function(spaces) {
$("<div class='info' />").text("You have " + spaces.length + " spaces.").insertBefore($(".spaceSearch")[0]);
$("form.spaceSearch input").autocomplete({
html: true,
source: function(req, response) {
ts.getSpaces(function(spaces) {
var selected = [];
for(var i = 0; i < spaces.length; i++) {
var space = spaces[i];
if(space.name.indexOf(req.term) > -1) {
var host = ts.getHost(space.name) ;
var img = host + "/SiteIcon";
selected.push({
value: space.name,
label: '<a href="' + host + '" target="_parent" class="autocompleteLink"><img src="' + img + '" style="height:24px;width:auto;max-height:24px;max-width:24px;"/>' + space.name + '</a>'
});
}
}
response(selected);
});
},
select: function(event, ui) {
window.top.location = ts.getHost(ui.item.value);
}
});
var $ul = $('.ts-space-search');
$.each(spaces, function(i, space) {
$ul.append($('<li/>').html($('<a/>').attr('href', space.uri)
.text(space.name)));
});
$('form.spaceSearch button').click(function(ev) {
$('.list-container').slideToggle('fast');
ev.preventDefault();
return false;
});
});
});
if(window != window.top) {
$("html").addClass("iframeMode");
$("a").live("click",function(ev) {
$(ev.target).attr("target", "_parent");
});
}
</script>
<!--[if lt IE 8]>
<script type="text/javascript" src="/bags/common/tiddlers/json2.js"></script>
<![endif]-->
</body>
</html>
In reply to [[StoryFodder 201207]]@cdent @cdent
At the next iteration of TiddlySapce development, I'd like to see.
!! Iteration Suggestions
<<<
* Simplify, clean and check for correctness the downloaded TiddlyWiki. Make it more like a plain tiddlywiki that could sync to a TiddlyWeb server that happens to be TiddlySpace.
<<<
While I'd really, really love to see that happen, I think the next two are more important.
<<<
* Redo the frontpage now that pre-existing constraints are gone.
<<<
I do like the existing frontpage. The only thing is: "The INTRO Buttons need to work". For me this is part of documentation.
<<<
* Do a documentation sprint and only a documentation sprint (yes, for two weeks, with snacks).
<<<
I think it would be worth, trying to get the community involved too.
<<<
* Allow signup via github or twitter or facebook. That is: figure out oAuth.
<<<
Would [[mozilla's browser id|https://browserid.org/about]] be an option too?
!! Remarks
<<<
* Collapse system-* stuff into one space whereby including or discluding it turns "tiddlyspaceness" on or off in a TiddlyWiki.
<<<
If I create "plugin spaces" I do remove all system-* bags ''except system-plugins'' since they are needed to handle the "make public / private" commands.
Like ben said in [[StoryFodder 201207]]@bengillies
> If anything, I'd say that changing the /_space app to put them all in the same box is a better idea.
----
!! Not Forgotten
* Audit and refactor {{{/_space}}} and {{{/_account}}}. Both have several (unrecorded) bugs and inscrutable code.
* Ditto {{{takenote}}}.
* Redo default HTML rep CSS to be aligned with the styles used in backstage, apps, space, account, etc.
* Create a simple search interface to go in universal backstage that uses {{{/hsearch}}}. The purpose is to encourage discovery in fuzzy ways (which {{{/search}}} is less good at). The output would need to be more verbose than a standard tiddlers collection, but have similar style.
* Make eastmad pick some stories.
* Make an interactive demo that demonstrates the reply/following/atbox ideas.
* Create a styleguide for TiddlySpace, align existing CSS etc accordingly.
* Make [[tsapp]].
* Move bookmark stuff into core.
It's difficult because to a certain extent many of these things aren't worth doing if the existing system is not:
* polished
* self-describing
Historically we've been shit at both those tasks //and// the story/iteration pattern hasn't serviced us well for accomplishing them. It may be better to just say that for the duration of the iteration people will actually work on (and use!) TiddlySpace rather than their several other responsibilities, with an eye to polish and documentation. It's a drag and a chore and often boring, but it has to be done.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="434 218 68 68"
width="30" height="30">
<g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
<g>
<path d="M 478.39694 232.53705 L 478.39694 232.53705
C 477.1145 231.85132 475.77875 231.30147 474.41058 230.88734 L 474.41058 218.24994 L 461.58942 218.24994
L 461.58942 230.88734 C 460.22125 231.30147 458.8855 231.85132 457.60306 232.53705 L 448.66824 223.60214
L 439.6022 232.66814 L 448.53717 241.60304 C 447.8515 242.8854 447.30157 244.22116 446.88745 245.58936
L 434.25 245.58936 L 434.25 258.41052 L 446.88745 258.41052
C 447.30157 259.77869 447.8515 261.11447 448.53717 262.39688 L 439.6022 271.33173 L 448.66824 280.3978
L 457.60306 271.46283 C 458.8855 272.14862 460.22125 272.69846 461.58942 273.11252 L 461.58942 285.74988
L 474.41058 285.74988 L 474.41058 273.11252 C 475.77875 272.69846 477.1145 272.14862 478.39694 271.46283
L 487.33176 280.3978 L 496.39767 271.33173 L 487.46286 262.39688
C 488.14853 261.11447 488.69836 259.77869 489.11255 258.41052 L 501.74988 258.41052 L 501.74988 245.58936
L 489.11255 245.58936 C 488.69836 244.22116 488.14853 242.8854 487.46286 241.60304 L 496.39767 232.66814
L 487.33176 223.60214 Z M 475.3328 244.66714 C 479.3825 248.71698 479.3825 255.2829 475.3328 259.33273
C 471.28296 263.3826 464.71704 263.3826 460.66724 259.33273
C 456.61737 255.2829 456.61737 248.71698 460.66724 244.66714
C 464.71704 240.61734 471.28296 240.61734 475.3328 244.66714" fill="#111"
class="glyph"/>
</g>
</g>
</svg>
<<tiddler FollowTemplate>>
! Rethinking ~TiddlySpace
Jon writes about [[Rethinking TiddlySpace]]@jon
<<<
If I was making TiddlySpace now from scratch I would seriously consider dramatically changing our current definition of the home space. A home space would define customisations that work across TiddlySpace not over a single space. For instance to pmario his space would look like it does currently. However I could override this to give myself a view of his space with my non-TiddlyWiki customisations. A non-TiddlySpace user would get pmario's default TiddlyWiki theme.
<<<
That's why I like the "ImportExternalLinksPlugin" from the @following space. It loads the content from other spaces, into my space, so I can view it, in a way that I like. The only annoyance is, that "alien" macros are not rendered. For me, this not a big deal, I just ignore it. But thinking about visitors, I should deal with that.
In my own tiddlers, I do avoid 3^^rd^^ party plugins as much as possible. Which will be also needed if you want to have a working server side rendered HTML presentation.
ColorPalette
StyleSheet
SiteSubtitle
GettingStarted
SiteTitle
MainMenu
SiteIcon
DefaultTiddlers
ViewTemplate
PageTemplate
SideBarOptions
EditTemplate
SiteInfo
SideBarTabs
ToolbarCommands
<<tiddler FollowTemplate>>
I created a {{{<<list>> macro}}} [[Railroad diagram|ListRailroadGrammar]]@pmario with http://railroad.my28msec.com/rr/ui to get an overview about the new filters defined at @filters space. I need to know, how it will work together with my plugins [1], if I rewrite them:
[1] http://apm-plugins.tiddlyspot.com/#NumberedTextListPlugin%20XCaseListPlugin%20NoCaseListPlugin
!!!!I like:
{{{[is[ ]]}}} - image or svg
{{{[notag[ ]]}}} - filters result of previous filters for ones without a tag
{{{[nofield[ ]]}}} - check for absence of field or field value in previous filters
{{{[has[ ]]}}} - match tiddlers which have a field or attribute set.
!!!!I think:
{{{[and[tag:foo]]}}} is the same as [tag[anyTag]] [tag[foo]]
*I'd use ~MatchTagsPlugin for {{{[tag[tag1 OR tag2 AND tag3]]}}}
!!!!I would like to have:
{{{[has[field:fieldName:value]]}}} - returns all tiddlers that have the fieldName and the right value.
{{{[has[field:fieldName]]}}} - return all tiddlers that have the fieldName
{{{[hasno[field:fieldName:value]]}}} - returns all tiddlers, except those which have a full match
{{{[hasno[field:fieldName]]}}} - returns all tiddlers, except those which have the fieldName match
{{{[nofield[ ]]}}} - can be used as a shorthand for {{{[hasno[field:fieldName]]}}} .. The discription of "nofield" is not precise enough!
{{{[hasno[tag:tagName]]}}} - returns all tiddlers not tagged with "tagName"
{{{[hasno[tag:]]}}} - returns all tiddlers, that have no tag
{{{[notag[]]}}} .. can be used as a shorthand for {{{[hasno[tag]]}}}
I am not sure what "[has[]] attribute" means in jon's description.
~@jon .. is there a repo at github?
The title and subtitle of your space are visible to visitors and are also displayed in your browser's tabs. Click on the SiteTitle and SiteSubtitle tiddler links below to make changes.
* [[SiteTitle]]
* [[SiteSubtitle]]
<<tsScan pmario tag:contact fat:y template:"ScanTests##contact">>
{{{
<<tsScan pmario tag:contact fat:y template:"ScanTests##contact">>
}}}
//{{{
!contact
|<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>>|@$1 wants to contact me|
<<view text text>>
!end
//}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<path id="iconSymbol" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m21.411,59.069,3.5152,4.3939,9.7922-11.675" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4" stroke-width="2.4000001" fill="none"/>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
/*{{{*/
[[StyleSheetTiddlySpaceMp]]
[[StyleSheetMediaPrint]]
/*}}}*/
<!--{{{-->
<div macro='slideRevision'></div>
<div class='heading'>
<span class="titleBar">
<div class='title' macro='view title text'></div>
</span>
<span class='modifierIcon'
macro='view modifier SiteIcon label:no height:48 width:48 preserveAspectRatio:yes'>
</span>
<div class='toolbar'
macro='toolbar [[ToolbarCommands::RevisionToolbar]] icons:yes height:48 width:48 more:popup'>
</div>
<div class='tagClear'></div>
</div>
<div class='content'>
<div class='viewer' macro='view text wikified'></div>
</div>
<div class='tagInfo'>
<div class='tidTags' macro='tags'></div>
<div class='tagging' macro='tagging'></div>
</div>
<!--}}}-->
<<tiddler TEMPLATES##follow>>
/***
|''Requires''|codemirror.js|
|''License''|[[codemirror.js]]|
***/
//{{{
CodeMirror.defineMode("htmlmixed",function(e,t){function s(e,t){var s=n.token(e,t.htmlState);return s=="tag"&&e.current()==">"&&t.htmlState.context&&(/^script$/i.test(t.htmlState.context.tagName)?(t.token=u,t.localState=r.startState(n.indent(t.htmlState,"")),t.mode="javascript"):/^style$/i.test(t.htmlState.context.tagName)&&(t.token=a,t.localState=i.startState(n.indent(t.htmlState,"")),t.mode="css")),s}function o(e,t,n){var r=e.current(),i=r.search(t);return i>-1&&e.backUp(r.length-i),n}function u(e,t){return e.match(/^<\/\s*script\s*>/i,!1)?(t.token=s,t.localState=null,t.mode="html",s(e,t)):o(e,/<\/\s*script\s*>/,r.token(e,t.localState))}function a(e,t){return e.match(/^<\/\s*style\s*>/i,!1)?(t.token=s,t.localState=null,t.mode="html",s(e,t)):o(e,/<\/\s*style\s*>/,i.token(e,t.localState))}var n=CodeMirror.getMode(e,{name:"xml",htmlMode:!0}),r=CodeMirror.getMode(e,"javascript"),i=CodeMirror.getMode(e,"css");return{startState:function(){var e=n.startState();return{token:s,localState:null,mode:"html",htmlState:e}},copyState:function(e){if(e.localState)var t=CodeMirror.copyState(e.token==a?i:r,e.localState);return{token:e.token,localState:t,mode:e.mode,htmlState:CodeMirror.copyState(n,e.htmlState)}},token:function(e,t){return t.token(e,t)},indent:function(e,t){return e.token==s||/^\s*<\//.test(t)?n.indent(e.htmlState,t):e.token==u?r.indent(e.localState,t):i.indent(e.localState,t)},compareStates:function(e,t){return n.compareStates(e.htmlState,t.htmlState)},electricChars:"/{}:"}}),CodeMirror.defineMIME("text/html","htmlmixed");
//}}}
A users point of view:
If you use ~TiddlySpace you are online most of the time. But if you have a Laptop with a GSM or WIFI and change position. It is quite common to loose the connection. If so, loading a tiddler, that is not part of the TW allready, will result in "Please wait, while loading ..."
Can you see the smile on the faces of your audience :)
The quick fix will be. Leaving the room and download the whole stuff, if you find the right spot, and work offline.
Nice.
Hopefully they are still smiling, if you are back.
Now you can try to make a good second impression. The first impression is history.
----
One very important factor, using TW is, that you can trust it. If the page is loaded.
Whatever you need, is there. It doesn't matter, if you are online or offline.
I don't want to miss that.
I'd vote for the "nice and simple" approach, even if it means to wait a little bit at startup.
If the "smart" approach is, that ''I'' can decide/configure ''what'' is loaded, ''when'' it is loaded and if I didn't configure it, everything is loaded. I'd vote for "smart"
----
I think {{{<<tsSearch>> or <<tsScan>>}}} with some saved (predefined) queries can do the "lazy" searching. The existing plugins can do the inline search.
----
Also see: [[beefcake is back]]@pmario
!Others say
<<tsScan [[Dynamic Loading]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
/***
|''Name''|TiddlySpaceBackstage|
|''Version''|0.8.0|
|''Description''|Provides a TiddlySpace version of the backstage and a homeLink macro|
|''Status''|@@beta@@|
|''Contributors''|Jon Lister, Jon Robson, Colm Britton|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceBackstage.js|
|''Requires''|TiddlySpaceConfig ImageMacroPlugin TiddlySpaceViewTypes|
!StyleSheet
.tiddler .error.annotation .button{
display: inline-block;
}
#backstageArea {
z-index: 49;
color: white;
background-color: black;
background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #222),color-stop(0.5, #333),color-stop(1, #555));
background: -moz-linear-gradient(center bottom,#222 0%, #333 50%, #555 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff555555, endColorstr=#ff222222);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#ff555555, endColorstr=#ff222222)";
height: 25px;
padding: 0;
}
#backstageButton {
overflow: hidden;
}
#backstageButton #backstageShow,
#backstageButton #backstageHide {
margin: 0px;
padding: 0px;
}
#backstageButton #backstageShow:hover,
#backstageButton #backstageHide:hover {
background: none;
color: none;
}
#backstageButton img,
#backstageButton svg {
width: 24px;
height: 24px;
}
#messageArea {
top: 50px;
}
#backstageToolbar {
position: relative;
}
#backstageArea a {
padding: 0px;
margin-left: 0px;
color: white;
background: none;
}
#backstageArea a:hover {
background-color: white;
}
#backstage ol,
#backstage ul {
padding: auto;
}
#backstageButton a {
margin: 0;
}
.backstagePanelBody ul {
padding: 5px;
margin: 5px;
}
#backstage #backstagePanel {
margin-left: 5%;
padding: 0em;
margin-right: 5%;
}
#backstageToolbar a {
position: relative;
}
#backstageArea a.backstageSelTab,
#backstageToolbar .backstageTask {
line-height: 25px;
color: #767676;
}
.backstageTask .externalImage,
.backstageTask .image {
display: inline;
}
#backstageToolbar a span {
z-index: 2;
}
a.backstageTask {
display: inline;
margin-left: 1em !important;
}
.backstagePanelBody .button {
display: inline-block;
margin-right: 10px;
}
.backstagePanelBody {
margin: 0 0 0 0.6em;
padding: 0.4em 0.5em 1px 0.5em;
}
#backstage table {
margin: auto;
}
#backstage .wizard table {
border: 0px;
margin: 0;
}
#backstage div li.listLink {
border: 0px;
width: 78%;
font-size: 0.7em;
}
#backstage div li.listTitle {
font-weight: bold;
text-decoration: underline;
font-size: 1em;
background: #ccc;
width: 100%;
}
#backstage fieldset {
border: solid 1px [[ColorPalette::Background]];
}
#backstage .viewer table,#backstage table.twtable {
border: 0px;
}
#backstageToolbar img {
padding: 0;
}
#backstage .wizard,
#backstage .wizardFooter {
background: none;
}
.viewer td, .viewer tr, .twtable td, .twtable tr {
border: 1px solid #eee;
}
#backstage .inlineList ul li {
background-color: [[ColorPalette::Background]];
border: solid 1px [[ColorPalette::TertiaryMid]];
display: block;
float: left;
list-style: none;
margin-right: 1em;
padding: 0.5em;
}
.backstageClear, .inlineList form {
clear: both;
display: block;
margin-top: 3em;
}
.tiddlyspaceMenu {
text-align: center;
}
span.chunkyButton {
display: inline-block;
padding: 0;
margin: 0;
border: solid 2px #000;
background-color: #04b;
}
span.chunkyButton a.button, span.chunkyButton a:active.button {
white-space: nowrap;
font-weight: bold;
font-size: 1.8em;
color: #fff;
text-align: center;
padding: 0.5em 0.5em;
margin: 0;
border-style: none;
display: block;
}
span.chunkyButton:hover {
background-color: #014;
}
span.chunkyButton a.button:hover {
border-style: none;
background: none;
color: #fff;
}
#backstage .unpluggedSpaceTab .wizard,
.unpluggedSpaceTab .wizard {
background: white;
border: 2px solid #CCC;
padding: 5px;
}
.syncKey .keyItem {
border: 1px solid black;
display: inline-block;
margin: 0.2em;
padding: 0.1em 0.1em 0.1em 0.1em;
}
.keyHeading {
font-size: 2em;
font-weight: bold;
margin: 0.4em 0em -0.2em;
}
.unpluggedSpaceTab .putToServer,
.unpluggedSpaceTab .notChanged {
display: none;
}
.tiddlyspaceMenu ul {
margin: 0;
padding: 0;
}
.tiddlyspaceMenu ul li {
list-style: none;
}
.unsyncedChanges .unsyncedList {
display: block;
}
.unsyncedList {
display: none;
}
!Code
***/
//{{{
(function ($) {
var name = "StyleSheet" + tiddler.title;
config.shadowTiddlers[name] = "/*{{{*/\n%0\n/*}}}*/".
format(store.getTiddlerText(tiddler.title + "##StyleSheet")); // this accesses the StyleSheet section of the current tiddler (the plugin that contains it)
store.addNotification(name, refreshStyles);
if (!config.extensions.tiddlyweb.status.tiddlyspace_version) { // unplugged
config.extensions.tiddlyweb.status.tiddlyspace_version = "<unknown>";
config.extensions.tiddlyweb.status.server_host = {
url:config.extensions.tiddlyweb.host }; // TiddlySpaceLinkPlugin expects this
}
var disabled_tasks_for_nonmembers = ["tiddlers", "plugins", "batch", "sync"];
var tweb = config.extensions.tiddlyweb;
var tiddlyspace = config.extensions.tiddlyspace;
var currentSpace = tiddlyspace.currentSpace.name;
var imageMacro = config.macros.image;
if (config.options.chkBackstage === undefined) {
config.options.chkBackstage = false;
}
// Set up Backstage
config.tasks = {};
config.tasks.status = {
text:"status",
tooltip:"TiddlySpace Info",
content:"<<tiddler Backstage##Menu>>"
};
config.tasks.tiddlers = {
text:"tiddlers",
tooltip:"tiddlers control panel",
content:"<<tiddler Backstage##BackstageTiddlers>>"
};
config.tasks.plugins = {
text:"plugins",
tooltip:"Manage installed plugins",
content:"<<tiddler Backstage##Plugins>>"
};
config.tasks.batch = {
text:"batch",
tooltip:"Batch manage public/private tiddlers",
content:"<<tiddler Backstage##BatchOps>>"
};
config.tasks.tweaks = {
text:"tweaks",
tooltip:"Tweak TiddlyWiki behaviors",
content:"<<tiddler Backstage##Tweaks>>"
};
config.tasks.exportTiddlers = {
text:"import/export",
tooltip:"Import/export tiddlers from/to a TiddlyWiki",
content:"<<tiddler Backstage##ImportExport>>"
};
config.tasks.sync = {
text:"sync",
tooltip:"Check Sync status",
content:"<<tiddler Backstage##SpaceUnplugged>>"
};
if (window.location.protocol === "file:") {
config.unplugged = true;
}
config.backstageTasks = ["status", "tiddlers", "plugins",
"batch", "tweaks", "exportTiddlers", "sync"];
config.messages.backstage.prompt = "";
// initialize state
var _show = backstage.show;
backstage.show = function () {
// selectively hide backstage tasks and tabs based on user status
var tasks = $("#backstageToolbar .backstageTask").show();
var bs = backstage.tiddlyspace;
if (!config.unplugged) {
tweb.getUserInfo(function (user) {
if (user.anon) {
jQuery.each(disabled_tasks_for_nonmembers, function (i, task) {
var taskIndex = config.backstageTasks.indexOf(task);
if (taskIndex !== -1) {
config.backstageTasks.splice(taskIndex, 1);
}
});
config.messages.memberStatus = bs.locale.loggedout;
} else {
config.messages.memberStatus = readOnly ?
bs.locale.nonmember : bs.locale.member;
}
});
} else {
config.messages.memberStatus = bs.locale.unplugged;
}
// display backstage
return _show.apply(this, arguments);
};
if (readOnly) {
jQuery.each(disabled_tasks_for_nonmembers, function (i, task) {
var taskIndex = config.backstageTasks.indexOf(task);
if (taskIndex !== -1) {
config.backstageTasks.splice(taskIndex, 1);
}
});
}
var tasks = config.tasks;
var commonUrl = "/bags/common/tiddlers/%0";
backstage.tiddlyspace = {
locale:{
member:"You are a member of this space.",
nonmember:"You are not a member of this space.",
loggedout:"You are currently logged out of TiddlySpace.",
unplugged:"You are unplugged."
},
showButton:function () {
var showBtn = $("#backstageShow")[0];
var altText = $(showBtn).text();
$(showBtn).empty();
imageMacro.renderImage(showBtn, "backstage.svg",
{ altImage:commonUrl.format("backstage.png"), alt:altText});
},
hideButton:function () {
var hideBtn = $("#backstageHide")[0];
var altText = $(hideBtn).text();
$(hideBtn).empty();
imageMacro.renderImage(hideBtn, "close.svg",
{ altImage:commonUrl.format("close.png"), alt:altText, width:24, height:24 });
}
};
var _init = backstage.init;
backstage.init = function () {
_init.apply(this, arguments);
var init = function (user) {
var bs = backstage.tiddlyspace;
bs.showButton();
bs.hideButton();
};
tweb.getUserInfo(init);
};
var home = config.macros.homeLink = {
locale:{
linkText:"your home space"
},
handler:function (place) {
var container = $("<span />").appendTo(place)[0];
tweb.getUserInfo(function (user) {
if (!user.anon && user.name !== currentSpace) {
createSpaceLink(container, user.name, null, home.locale.linkText);
}
});
}
};
config.macros.exportSpace = {
handler:function (place, macroName, params) {
var filename = params[0] ||
"/tiddlers.wiki?download=%0.html".format(currentSpace);
$('<a class="button">download</a>').// XXX: i18n
attr("href", filename).appendTo(place);
}
};
}(jQuery));
//}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#FF4646" offset="0"/>
<stop id="stop2" stop-color="#ffcccc" offset="0.66462"/>
<stop id="stop3" stop-color="#FF4646" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol">
<path id="path3645" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m-23.302,17.497c0.01395-0.0064,0.0156,0.0261,0.0143,0.03143-0.01484,0.061-0.10068,0.05137-0.14,0.02579-0.11849-0.07708-0.08526-0.2504-0.003-0.34004,0.17365-0.18931,0.47534-0.11872,0.63154,0.05396,0.27503,0.30406,0.15201,0.77586-0.14521,1.0145-0.46844,0.3761-1.1521,0.18524-1.4889-0.27069-0.49266-0.6669-0.21843-1.6041,0.43042-2.0548,0.89949-0.62476,2.1319-0.25161,2.7121,0.62439,0.77241,1.1662,0.28478,2.7356-0.8526,3.4609-1.4672,0.93564-3.4151,0.31794-4.3011-1.1151-1.1144-1.8023-0.3511-4.1704,1.4118-5.2328,2.1717-1.3088,5.0016-0.38425,6.256,1.7427,1.5188,2.5753,0.4174,5.9087-2.1079,7.3706-3.0131,1.7444-6.8916,0.45055-8.5767-2.5073-1.9855-3.4851-0.48369-7.9504,2.941-9.8743,3.9914-2.2422,9.0851-0.51682,11.263,3.4089" transform="matrix(1.02832, 0, 0, 1.02832, 51.2465, 40.8719)" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4" stroke-width="1.55593979000000000" fill="none"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
* If they are nice and small in size: yes.
/***
related to: [[plugin meta markup for tiddlywiki]]@pmario
Four versions to create any shadowTiddler (StyleSheet, Configuration tiddlers ...) with different type of abstraction, to make modification for a developer as easy as possible. And the reuse of code simple.
* It should render well if seen as source code.
* The produced shadow tiddlers should render well if viewed.
* If the user changes the ~StyleSheet the TW should be redrawn automatically, without reloading the page.
***/
//{{{
(function($) {
//}}}
/***
!First Version
* creates 2 additional local variables, which can be nicely minified
* hacking the code should be straight forward.
* The user only needs to change {{{styleSheetName}}} and the content.
* It produces [[fancyStyleSheet]], which contains some customer information as a comment. Click the link to change/view the tiddler.
***/
//{{{
var styleSheetName = "fancyStyleSheet"
var styleDefinitions = [
".myClass {",
" font-size: 0.9em; /* Some info for the user, why the developer did it that way */",
"}"
];
config.shadowTiddlers[styleSheetName] = "/*{{{*/\n"+ styleDefinitions.join('\n') + "\n/*}}}*/";
store.addNotification(styleSheetName,refreshStyles);
//}}}
/***
!Second Version
* The name of the shadow tiddler has to be entered as a string, at the end, which is a little bit harder to maintain.
** {{{config.shadowTiddlers["myFancyStyleSheet"]}}}
** {{{store.addNotification("myFancyStyleSheet",refreshStyles);}}}
* creates 1 additional local variables, which doesn't need to be changed.
* hacking the code should be straight forward.
* The user only needs to change the content.
* It produces [[myFancyStyleSheet]]
***/
//{{{
var styles = [
".myClass {",
" font-size: 0.9em;",
"}"
];
config.shadowTiddlers["myFancyStyleSheet"] = "/*{{{*/\n"+ styles.join('\n') + "\n/*}}}*/";
store.addNotification("myFancyStyleSheet",refreshStyles);
//}}}
/***
!Third Version
* The name of the shadow tiddler has to be entered at the beginning and at the end of the function, which is a little bit harder to maintain.
** {{{config.shadowTiddlers["myFancyStyleSheet"]}}}
** {{{store.addNotification("myFancyStyleSheet",refreshStyles);}}}
* It doesn't create any unused variables.
* hacking the code should be straight forward.
* The user only needs to change the content.
* It produces [[myFancyStyleSheet_]]
***/
//{{{
config.shadowTiddlers["myFancyStyleSheet_"] = "/*{{{*/\n"+ [
".myClass {",
" font-size: 0.9em;",
"}"
].join('\n') + "\n/*}}}*/";
store.addNotification("myFancyStyleSheet_",refreshStyles);
//}}}
/***
!Fourth Version
* The name of the shadow tiddler has to be entered at the beginning and at the end of the function, which is a little bit harder to maintain.
** {{{config.shadowTiddlers["myFancyStyleSheet"]}}}
** {{{store.addNotification("myFancyStyleSheet",refreshStyles);}}}
* It doesn't create any unused variables.
* hacking the code is not straight forward, because you have to play with {{{'\n'}}} and string concatination.
* The user only needs to change the content, which may be tricky :)
* It produces [[StyleSheetMyPlugin]]
***/
//{{{
config.shadowTiddlers["StyleSheetMyPlugin"]="/*{{{*/\n"+
".myClass {\n"+
" font-size: 0.9em;\n"+
"}\n"+
"/*}}}*/";
store.addNotification("StyleSheetMyPlugin",refreshStyles);
//}}}
//{{{
})(); //# end of alias
//}}}
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAKGmlDQ1BJQ0MgUHJvZmlsZQAAeAHVlmdUFMkWx6t7ciLNkNOQc84gOSfJUVSGAYY4wpAxIbK4AooiIgLKEpao4KoEWQMiigERUEBF3UEWAWVdDIiKyuuBd9w977z99r6826eqfn3r9q3quvXhDwDpIyMpKQEWACCRncrxdbajB4eE0nGTAAIUgAe6wJDBTEmy9fb2AP9oH8aRaMTua/Fy/WPYf58QjIxKYQIAeSPTEZEpzESEzyNsyEzipCI8h/BwRmoSwnA3wjQOskGEB3nMWmcujyPW+f1ajL+vPQAoPAB4MoPBYQFAoiF+ejqTheQhGSKsy46MZSMcibAVM4aBjKR6hDUTE7fxeBhh1Yi/5WH9jRmMiO85GQzWd17/F+RLZGGH2JSkBEbW2sv/sktMSEPOa814p06OYgf4IaMY0qSAA3AEHshDB/rABKmeCQgCTsA7NSoT+W8A7LclZXFiWTGpdFukUlGadFc2U1uTrq+rp8eb/r8x3h1d3+y7e2t3DxLjlf/fvmRtAMwakPr3/uULfw5A510ARPr/8ineAID/AADdTcw0Tvp6PjRvwAAi4Ac0IA5kgAJQBVrIaRoDC2CDnK4b8AL+IARsAUwQAxIBB2SAHWAPyAeF4BA4CipANagDTeA0OAu6wEVwFdwAd8AwGAOTgAtmwCuwCD6AFQiCcBAFokLikCykBGlA+pApZAU5Qh6QLxQChUMsiA2lQTugvVAhVAJVQDVQM/QLdAG6Ct2CRqBH0BQ0D72FPsMomAzTYGlYGdaBTWFb2B32hzfDLDgZzobz4INwOVwLn4I74avwHXgM5sKv4CUUQJFQIig5lBbKFGWP8kKFoqJRHNQuVAGqDFWLakP1oAZQ91Fc1ALqExqLpqLpaC20BdoFHYBmopPRu9BF6Ap0E7oT3Y++j55CL6K/YSgYKYwGxhzjignGsDAZmHxMGaYB04G5jhnDzGA+YLFYEawK1gTrgg3BxmG3Y4uwJ7Dt2F7sCHYau4TD4cRxGjhLnBeOgUvF5eOO407hruBGcTO4j3gSXhavj3fCh+LZ+Fx8Gb4Ffxk/ip/FrxAECEoEc4IXIZKQRSgm1BN6CPcIM4QVoiBRhWhJ9CfGEfcQy4ltxOvEJ8R3JBJJnmRG8iHFknJI5aQzpJukKdInshBZnWxPDiOnkQ+SG8m95EfkdxQKRZliQwmlpFIOUpop1yjPKB/5qHzafK58kXy7+Sr5OvlG+V7zE/iV+G35t/Bn85fxn+O/x78gQBBQFrAXYAjsEqgUuCAwIbAkSBXUE/QSTBQsEmwRvCU4J4QTUhZyFIoUyhOqE7omNE1FURWo9lQmdS+1nnqdOkPD0lRorrQ4WiHtNG2ItigsJGwoHCicKVwpfEmYK4ISURZxFUkQKRY5KzIu8llUWtRWNEp0v2ib6KjospikmI1YlFiBWLvYmNhncbq4o3i8+GHxLvGnEmgJdQkfiQyJkxLXJRYkaZIWkkzJAsmzko+lYCl1KV+p7VJ1UoNSS9Iy0s7SSdLHpa9JL8iIyNjIxMmUylyWmZelylrJxsqWyl6RfUkXptvSE+jl9H76opyUnItcmlyN3JDciryKfIB8rny7/FMFooKpQrRCqUKfwqKirKKn4g7FVsXHSgQlU6UYpWNKA0rLyirKQcr7lLuU51TEVFxVslVaVZ6oUlStVZNVa1UfqGHVTNXi1U6oDavD6kbqMeqV6vc0YA1jjViNExojmhhNM022Zq3mhBZZy1YrXatVa0pbRNtDO1e7S/u1jqJOqM5hnQGdb7pGugm69bqTekJ6bnq5ej16b/XV9Zn6lfoPDCgGTga7DboN3hhqGEYZnjR8aEQ18jTaZ9Rn9NXYxJhj3GY8b6JoEm5SZTJhSjP1Ni0yvWmGMbMz22120eyTubF5qvlZ8z8ttCziLVos5jaobIjaUL9h2lLekmFZY8m1oluFW/1kxbWWs2ZY11o/t1GwibRpsJm1VbONsz1l+9pO145j12G3bG9uv9O+1wHl4OxQ4DDkKOQY4Fjh+MxJ3onl1Oq06GzkvN251wXj4u5y2GXCVdqV6drsuuhm4rbTrd+d7O7nXuH+3EPdg+PR4wl7unke8XyyUWkje2OXF/By9Tri9dRbxTvZ+1cfrI+3T6XPC1893x2+A35Uv61+LX4f/O38i/0nA1QD0gL6AvkDwwKbA5eDHIJKgrjBOsE7g++ESITEhnSH4kIDQxtClzY5bjq6aSbMKCw/bHyzyubMzbe2SGxJ2HJpK/9WxtZz4ZjwoPCW8C8ML0YtYynCNaIqYpFpzzzGfBVpE1kaOR9lGVUSNRttGV0SPceyZB1hzcdYx5TFLMTax1bEvolziauOW473im+MX00ISmhPxCeGJ15gC7Hj2f3bZLZlbhtJ0kjKT+ImmycfTV7kuHMaUqCUzSndqTREDAymqab9kDaVbpVemf4xIzDjXKZgJjtzMEs9a3/WbLZT9s/b0duZ2/t2yO3Ys2Nqp+3Oml3QrohdfbsVduftnslxzmnaQ9wTv+durm5uSe77vUF7e/Kk83Lypn9w/qE1ny+fkz+xz2Jf9Y/oH2N/HNpvsP/4/m8FkQW3C3ULywq/FDGLbh/QO1B+YPVg9MGhYuPik4ewh9iHxg9bH24qESzJLpk+4nmks5ReWlD6/ujWo7fKDMuqjxGPpR3jlnuUdx9XPH7o+JeKmIqxSrvK9iqpqv1VyyciT4yetDnZVi1dXVj9+afYnx7WONd01irXltVh69LrXtQH1g/8bPpzc4NEQ2HD10Z2I7fJt6m/2aS5uUWqpbgVbk1rnT8Vdmr4tMPp7jattpp2kfbCM+BM2pmXv4T/Mn7W/WzfOdNzbeeVzld1UDsKOqHOrM7FrpgubndI98gFtwt9PRY9Hb9q/9p4Ue5i5SXhS8WXiZfzLq9eyb6y1JvUu3CVdXW6b2vf5LXgaw/6ffqHrrtfv3nD6ca1AduBKzctb168ZX7rwm3T2113jO90DhoNdtw1utsxZDzUec/kXvew2XDPyIaRy6PWo1fvO9y/8cD1wZ2xjWMj4wHjDyfCJrgPIx/OPUp49OZx+uOVyZwnmCcFTwWelj2Telb7m9pv7Vxj7qUph6nB537PJ6eZ069+T/n9y0zeC8qLslnZ2eY5/bmL807zwy83vZx5lfRqZSH/D8E/ql6rvj7/p82fg4vBizNvOG9W3xa9E3/X+N7wfd+S99KzD4kfVpYLPop/bPpk+mngc9Dn2ZWML7gv5V/VvvZ8c//2ZDVxdTWJwWGsaQEU0sPR0QC8bQSAEgIAFdGExN51DbkWAa3rXoR5SozXePYfvK4z12aMAajrBcDfBgAPZKzMAUAZYX6k8eSvP7KegcH3hnh4lhJtoL8GEFkCkSa9q6tvVwHAhQPwdWh1daV8dfVrGaJ13gNwZeO6duVFC5xCZDPVUE/Xry/9cA7P83f7FxpgvJtcDRvaAAAACXBIWXMAAAsTAAALEwEAmpwYAAAH+ElEQVRoBdVZa2xcxRWemXv37vq5dvxIbMdvEoNLCJQkJlBofkRR0poFq7hSBYlCBeIVojZ2ALWoriWo1OAEVaEhpKJINJUqWQ3CDgKqBKlNKdhJFCck69he4ziO4/gRr3dt7+69e+9MzxjZLLuz9u7m7g9Gsjz3zMyZ75s558yZWcwYQ9/nQr7P4Dl22WwC+9o77pMwrkMMlRGMixnCpQizPIywByE2DDs+zCgeoIS2+c76P2tq2qTfCgZshgm1fPC/fCzJOwkhv2SIVRGCDauisBSrVVIUC7ZYLEjXdaQFg0jTdMPn9yODUuCJJxmlrRozWl5xbHQlQuSWCRxo66xHEvkLYizTnpnBVuTmkLxlWUiSpKh4KKXI7fGisZtuNOF2AxemM8p+N3POdyDeHUmYQPPfOzIz7PggQnhHZnq6UVVRKqWm2KKCjtbAd8U1OMTGb7ox9DlPg8EtjXX3j0XrHy5PiMDugx9by8tz/o0QWV+6soCUFK5AYA7huuP6nnBPocuuAb4b5w335EON27fMxqIgoShUWp7zLjjnhupVFaS0qGBR8NzHVE0DC1s8XOdmZyHQx+3ubpyV3drc3BwTtrij0IH2jkaMyeMVxUUoF2xdVILgsAND19GU16sHAhoBxyYQhajNZqXgH3JJYQH4SCS+ZVl2tKq8mPQOXN2Wds/Wn4Puf4j0h8riMqE/tp6wW1LsQ7BaGT9YXRmqZ6F+c8qDLvdfgaBjUAB+DMJpL4TRIUbRSrCytUDeoSgyrb6tQrZnpC+Mm6/wnTr7ldOYDajde366bs28PNr/uHZATrE/B4rSS1cWCvX5Ayrq7vvaMBjtQkH2eEPdht7wjvvaOtdhLXj0Ul9/5bo11bICITa0cF8qKSqQul0Dd77RdnrrXsf6T0Lbw+uR+xjeI+Qb3PTXObDN6akpIdJvq7DyAJ7N+H36o3sE4HnPlxwbzugqfTioG2rfwFWhY+Qty+Z+RTFmP/pWu7gWM4E/HDtVACrywU6F4YbHde/MjIQMY89v6zcOi6f7Rrr3ZzV9cIAd4eYGphbRle+CzapQmGhVRGOYIGYCsqzczsdGi/XXR8cZTDwxrV49GjaH8JNhdAbsHQdUVdiearPJkIpUCRtDhDETIJjk8XEWOdJtAqqGbkIchyD+TlN9vRaiP3qVsrm5iSAa8UGUh12MA9EVfNMSMwGm0XN8CD9wwsvw6BgEG0bVgPF2eFu0b8iXfmGxyDrkS8IuAUiaKKNDwsYQYcwEuN0CyqOD10bo8I0xMHUDwamJRsYm0LWRUR793lvK9ufn3X+88ylY3p+UFKyQub2HF76jfn9AgvnmFi28PfQ70h5CW8PqwYBnF5wDaZC71PVD/gIgAPecKXw2HDB2h3UXfrZ8+OVmSZbfyrZn0qIV+cIFHBkbh7GYGUH6vlBJiDCug2x+3BvtX/yYMKkG5rCBKXcuFavnx81lroQcTUuxSWurV0sif/LOzKKuSz2wt/Sfe2o38NN40ZIQgUU1RmlsOX56N0H4zcyMNLRmdSWRBcGAh9QzF526qmp+nWq3v+R44HoUdQviuExoYVSclf3tna9DSPxN7jI7u6OyHMPFJ0IDd6Ker68wAE8YNXbGAp4rSTqB/e2n/wyO+nxBfi5aVVYC1Uin5Rccp2uAQSjGFKFfNTruOxbBMIogqQQOtJ9+E/A+X1ywHFWUrBRC4GZzsa+ferwzEPzRC42O9TGHYq4waT7QcrzjSYLIX4uW56PbyoqF4DUtiC709BmzPj9kFnR7o6NmyfQ5XFFSCOxr+7xQJooL0gHl3jXVEhxa4fMiXyCALnT3GkBC1RGt21tb86+ITjEIkmJChFhehbltVZVl4LAC8P4A6uru4XeGKarTrXsfrTkbA1Zhl8hwIOwWu/CZI0cskDftWJ6bgzPT0yIGcrPpcvYYelB3UxZ8sOEWwHPlphOoKrznIbgAp+XlZEeA54KeK4MUrpwaNeimhtqNl4Wd4hCaTgDieTWfX7T607M+NOn2wJzs1YZHapxx4Iza1XwCc8+IiMmCh62JSTcAgRTH7303KqI4G0wnACcRPEBg4VXRMzML5xTqerl+M7yTmlNMJwDwe8GMiA8iTWjh6beXH1YMnQiV32rddAJMNz6FHfD0DQ5R/mzIC08VIAXnlx5sGDjuw2oxkkk5yPZ/2PEYlsnfMMOKYrVQCJmYv0bD8v8eUuTmxQDF25YUAhxES3tnOWH4CUZYFTxqjWLCPmiorflvvACX6p80AktNbFa76T5gFrBY9SQlF+KTXz58shZesLdD/n8XY9QFT0AftY6dOtLU1MRDqWklKSbkPHziIKTSu2SrRVfSbLIe0AzNp/Kn8/8MBNUt217cJn7NSoCW6TvgPHTyMbgy7soszEFZJfnzzybS7LgHTbiGHyyTFR6FXkkAq3CI6T5AJPy0kmo1ADx/oF2YNC3PjuCPXymfXRCaUDGdAOQRP1QyUvkvkBHwrBmpXGa/cPBj8f0yYsTSAtMJwJTXDE0X5kIG3AWgBOXJmZh/xFuKgukE4AeCT/zuaaRO+78zN5BC0zfcOghPVTfF+AD8HQ3iD9MJ6D79NTCfwVHnFWNqaBz5gIzn+gQaOd9vUB0eC2nwGTGUxKRJCaMX/3RyuaTgw+AGDoDFF4n/dvC5StWn7npua09iUMWjkkJgfirnodZ0gu1Vs17iuvdl8+4A8/r5/6QSCJ0oWfX/A3UKXhQwWVptAAAAAElFTkSuQmCC
reply to bengillies
<<<
I'd like to point out that this feedback is also applied to the roundel in the middle of the backstage as well, so even if you close the tiddler it's still there.
<<<
* :) Backstage is closed ..
**There is an icon, a space name - (~12 cm of black space) - (tsIcon) tiddlyspace - (~12 cm of black space) user:pmario - icon
**It's just to much empty space in it.
But if it would look like:
*(tsIcon) tiddlyspace - (icon) space: spaceName - user: pmario (icon) - MessageArea (displaying the latest message)
**May be I'd keep it open. may be ...
*If i click the MessageArea and get a list of ~20 last messages it would be cool.
----
reply to jon
<<<
TiddlySpace now has better feedback for things such as saving:
* when you save a tiddler the roundel becomes the unsynced icon until a save
* errors on a save are displayed on the tiddler itself - edit conflicts allow resolution.
<<<
More feedback is nice. I actually don't like the message area default position. But I can't remove it. I automatically close it after 15 seconds.
I very often edit a tiddler - save - close tiddler. Where ''save - close tiddler'' is less then 500ms. I need the message area feedback, since the tiddler is closed allready, when the browser gets the feedback, that it is saved. At the moment, I also have firebug opend, viewing XHR requests to be sure, what's going on. Call me paranoid, but at the moment, I simply don't trust the system.
Also the 2 different icons seem to create a "refresh the whole page" which causes a "do nothing for several seconds" penalty, if activity stream is opened. (using FF 3.6.13 ubuntu 10.10).
Saving this tiddler, activity stream opened is ~3.5 seconds
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
/***
|''Name''|ImageMacroPlugin|
|''Version''|0.9.4|
|''Description''|Allows the rendering of svg images in a TiddlyWiki|
|''Author''|Osmosoft|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Notes''|Currently only works in modern browsers (not IE)|
|''Requires''|BinaryTiddlersPlugin|
!Usage
{{{<<image SVG>>}}} will render the text of the tiddler with title SVG as an SVG image (but not in ie where it will fail silently)
!!Parameters
width/height: specify width/height parameters
link: make the image link to a given location
tiddlyLink: link to a tiddler
!Notes
Binary tiddlers in TiddlyWeb when passed through the wikifier will be shown as images.
eg. {{{<<view text wikified>>}}} on a binary tiddler will show the image.
{{{<<view fieldname image>>}}}
will render the value of the tiddler field 'fieldname' as an image. This field can contain a tid
{{{<<image SiteIcon>>}}}
will create an image tag where the tiddler has content type beginning image and not ending +xml
will attempt to create svg object in other scenarios
{{{<<image /photos/x.jpg>>}}}
will create an image tag with src /photos/x.jpg as long as there is not a tiddler called /photos/x.jpg in
which case it will render that tiddler as an image. Note for the case of svg files it will attempt to render as an svg if possible via the image
tag. It doesn't embed the svg in the dom for security reasons as svg code can contain javascript.
!Code
***/
//{{{
(function($) {
var macro = config.macros.image = {
shim: "/bags/common/tiddlers/shim",
ieVersion: config.browser.isIE ? parseInt(config.browser.ieVersion[1], 10) : false,
svgns: "http://www.w3.org/2000/svg",
xlinkns: "http://www.w3.org/1999/xlink",
svgAvailable: document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"),
_fixPrefix: 1,
_external_cache: {},
_image_tag_cache: {},
_image_dimensions: {},
locale: {
badImage: "This image cannot be displayed."
},
handler: function(place, macroName, params, wikifier, paramString, tiddler){
var imageSource = params[0];
// collect named arguments
var args = macro.getArguments(paramString, params);
this.renderImage(place, imageSource, args);
},
init: function() {
var startupImages = store.getTaggedTiddlers("systemImage");
var place = $("<div />").attr("id", "systemImageArea").appendTo("body").hide()[0];
for(var i = 0; i < startupImages.length; i++) {
var image = startupImages[i];
macro.renderImage(place, image.title, { idPrefix: "" });
}
var data = new Image();
data.onload = function() {
// note ie 8 only supports data uris up to 32k so cannot be relied on
macro.supportsDataUris = this.width != 1 || this.height != 1 ? false : true;
macro.supportsDataUris = macro.ieVersion && macro.ieVersion < 9 ? false : macro.supportsDataUris;
};
data.onerror = data.onload;
data.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
},
refreshImage: function(src) {
var elements = macro._image_tag_cache[src] ? macro._image_tag_cache[src] : [];
if(macro._image_dimensions[src]) {
macro._image_dimensions[src] = false;
}
for(var i = 0; i < elements.length; i++) {
var el = $(elements[i]);
var newSrc = "%0?nocache=%1".format(src, Math.random());
el.attr("src", newSrc); // force reload
}
},
isBinaryImageType: function(contentType) {
return (contentType && contentType.indexOf("image") === 0 &&
contentType.indexOf("+xml") != contentType.length - 4) ? true : false;
},
isImageTiddler: function(tiddler) {
return macro.isSVGTiddler(tiddler) || macro.isBinaryImageTiddler(tiddler);
},
isSVGTiddler: function(tiddler) {
var type = tiddler ? tiddler.fields['server.content-type'] : false;
return type == "image/svg+xml";
},
isBinaryImageTiddler: function(tiddler) {
return macro.isBinaryImageType(tiddler.fields['server.content-type']);
},
renderImage: function(place, imageSource, options) {
var imageTiddler = store.getTiddler(imageSource);
var container;
var classes = ["image"];
if(options.link) {
classes = classes.concat(["imageLink", "externalLink"]);
container = $("<a />").attr("href", options.link).appendTo(place)[0];
} else if(options.tiddlyLink) {
classes.push("imageLink");
container = createTiddlyLink(place, options.tiddlyLink, false);
} else {
container = $("<span />").appendTo(place)[0];
}
$(container).addClass(classes.join(" "));
options = options ? options : {};
if(imageTiddler && macro.isBinaryImageTiddler(imageTiddler)) { // handle the case where we have an image url
return macro._renderBinaryImageTiddler(container, imageTiddler, options);
} else if(imageTiddler){ // handle the case where we have a tiddler
return macro._renderSVGTiddler(container, imageTiddler, options);
} else { // we have a string representing a url
return macro._renderBinaryImageUrl(container, imageSource, options);
}
},
_renderAlternateText: function(container, options) {
var img;
var src = options.src || "";
if(options.width && options.height) {
img = $("<img />").attr("src", src).addClass("svgImageText").attr("width", options.width).
attr("height", options.height).appendTo(container);
}
var alt = options.alt;
if(img && alt) {
img.attr("alt", alt).attr("title", alt);
} else if(alt) {
$(container).addClass("svgImageText").text(alt);
}
macro._image_tag_cache[src] = img;
},
_renderSVGTiddler: function(place, tiddler, options) {
if(!options) {
options = {};
}
merge(options, { tiddler: tiddler, fix: true});
if(macro.svgAvailable) {
this._importSVG(place, options); // display the svg
} else if(options.altImage) {
var image = options.altImage;
delete options.altImage;
this._renderBinaryImageUrl(place, image, options);
} else {
this._renderAlternateText(place, options); // instead of showing the image show the alternate text.
}
},
_renderBinaryImageTiddler: function(place, tiddler, options) {
var resourceURI;
var fields = tiddler.fields;
if(fields["server.type"] == "tiddlyweb") { // construct an accurate url for the resource
resourceURI = "%0/%1/tiddlers/%2".format(config.defaultCustomFields["server.host"],
fields["server.workspace"], encodeURI(fields["server.title"]));
} else { // guess the url for the resource
resourceURI = tiddler.title;
}
var ctype = fields["server.content-type"] || tiddler.type;
var text = tiddler.text;
if(macro.supportsDataUris && ctype && text.indexOf("<html") == -1) {
var uri = "data:%0;base64,%1".format(ctype, text);
options.src = resourceURI;
return macro._renderBinaryImageUrl(place, uri, options);
} else if(options.src) {
return macro._renderBinaryImageUrl(place, options.src, options);
} else {
return macro._renderBinaryImageUrl(place, resourceURI, options);
}
},
_renderImageTag: function(container, src, width, height, options) {
var img;
img = $("<img />").appendTo(container);
if(height) {
img.attr("height", height);
}
if(width) {
img.attr("width", width);
}
if(macro.ieVersion && macro.ieVersion < 7 && macro.shim && options.ie6png) {
$(img).css({width: userW, height: userH,
filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%0', sizingMethod='scale')".format(src)
}).attr("src", macro.shim);
} else {
img.attr("src", src);
}
if(!macro._image_tag_cache[options.srcUrl]) {
macro._image_tag_cache[options.srcUrl] = [];
}
img = $(img).addClass(options.imageClass)[0];
macro._image_tag_cache[options.srcUrl].push(img);
return img;
},
_getDimensions: function(realDimensions, reqDimensions, preserve) {
var w = realDimensions.width;
var h = realDimensions.height;
var reqh = reqDimensions.height;
var reqw = reqDimensions.width;
var finalw = w, finalh = h;
var ratiow = reqw / w, ratioh = reqh / h;
var scaledw = ratioh * w;
var scaledh = ratiow * h;
if(!reqw && reqh) {
finalw = scaledw;
finalh = reqh;
} else if(reqw && !reqh) {
finalw = reqw;
finalh = scaledh;
} else if(reqh && reqw) {
var preserveWidth = w > h ? true : false;
if(preserve) {
if(preserveWidth && scaledh < reqh) {
finalh = scaledh;
finalw = reqw;
} else {
finalh = reqh;
finalw = scaledw;
}
} else {
finalw = reqw;
finalh = reqh;
}
}
return { width: parseInt(finalw, 10), height: parseInt(finalh, 10) };
},
_renderBinaryImageUrl: function(container, src, options) {
var srcUrl = options.src ? options.src : src;
srcUrl = srcUrl.indexOf("/") === -1 ? "/%0".format(srcUrl) : srcUrl; // for IE.
var image_dimensions = macro._image_dimensions[srcUrl];
var image = new Image(); // due to weird scaling issues where you use just a width or just a height
var createImageTag = function(dimensions, error) {
if(error) {
var altImage = options.altImage;
if(altImage) {
delete options.altImage;
macro._renderBinaryImageUrl(container, altImage, options);
} else {
options.src = src;
macro._renderAlternateText(container, options);
}
} else {
var dim = macro._getDimensions(dimensions, {
width: options.width, height: options.height }, options.preserveAspectRatio);
options.srcUrl = srcUrl;
macro._renderImageTag(container, src, dim.width, dim.height, options);
}
};
if(!image_dimensions) {
image.onload = function() {
var dimensions = { width: image.width, height: image.height};
macro._image_dimensions[srcUrl] = dimensions;
createImageTag(dimensions);
};
image.onerror = function() {
createImageTag(null, true);
};
image.src = src;
} else {
createImageTag(image_dimensions);
}
},
_generateIdPrefix: function(){
return "twsvgfix_" + (this._fixPrefix++).toString() + "_";
},
_fixSVG: function(childNodes, idPrefix) {
var urlPattern = /url\(\#([^\)]*)\)*/ig;
var fixes = [
{ attr: "id", pattern: /^(.*)$/ig },
{ attr: "href", namespace: macro.xlinkns, pattern: /^#(.*)$/ig }
];
var url_fixes = ["filter", "fill", "mask", "stroke", "style"];
for(var i = 0; i < url_fixes.length; i++) {
fixes.push({ attr: url_fixes[i], pattern: urlPattern });
}
for(var t = 0; t < childNodes.length; t++) {
var node = childNodes[t];
for(var a = 0; a < fixes.length; a++) {
var fix = fixes[a];
var attr = fix.attr;
var ns = fix.namespace || "";
if(node.hasAttributeNS && node.hasAttributeNS(ns, attr)) {
var v = node.getAttributeNS(ns, attr);
fix.pattern.lastIndex = 0;
var match = fix.pattern.exec(v);
if(match) {
// Make sure replacement string doesn't contain any single dollar signs
var toReplace = match[1];
if(toReplace.indexOf(idPrefix) !== 0 && toReplace.indexOf("twglobal_") !== 0) {
var replacement = (idPrefix + toReplace).replace("$", "$$$$");
v = v.replace(match[1], replacement);
}
node.setAttributeNS(ns, attr,v);
}
}
}
var children = node.childNodes;
if(children.length > 0) {
this._fixSVG(children, idPrefix);
}
}
},
_importSVG: function(place, options){
options = options ? options : {};
var svgDoc, tiddlerText = options.tiddler.text;
if (window.DOMParser) {
svgDoc = new DOMParser().parseFromString(tiddlerText, "application/xml").documentElement;
var idPrefix = options.idPrefix || this._generateIdPrefix();
this._fixSVG([svgDoc], idPrefix);
var el = document.importNode(svgDoc, true);
var svgHolder = document.createElementNS(macro.svgns,"svg");
var width = options.width;
var height = options.height;
if(width || height) {
if(width && height) { // set view box of containing svg element based on the svg viewbox and width and height.
var viewBox = el.getAttribute("viewBox");
var topLeft = "0 0";
if(viewBox) {
topLeft = viewBox.replace(/([0-9]*) +([0-9]*) +([0-9]*) +([0-9]*) */gi,"$1 $2");
}
svgHolder.setAttributeNS(macro.svgns, "viewBox", "0 0 %0 %1".format(width, height));
} else {
if(!width) {
width = el.getAttribute("width");
}
if(!height) {
height = el.getAttribute("height");
}
}
svgHolder.setAttribute("width", width);
svgHolder.setAttribute("height", height);
el.setAttribute("width", "100%");
el.setAttribute("height", "100%");
svgHolder.setAttribute("class", "svgImage svgIcon %0".format(options.imageClass || ""));
svgHolder.appendChild(el);
place.appendChild(svgHolder);
}
else {
var existing = el.className ? el.className.baseVal : "";
el.setAttribute("class","svgImage %0".format(existing));
place.appendChild(el);
}
// if a tiddler attribute is set this is read as a link
$("[tiddler], [tiddlyLink]", place).attr("refresh", "link").click(function(ev) {
var tiddler = $(ev.target).attr("tiddlyLink");
if(tiddler) {
story.displayTiddler(ev.target, tiddler);
}
});
}
},
getArguments: function(paramString, params) {
var args = paramString.parseParams("name", null, true, false, true)[0];
var options = {};
for(var id in args) {
if(true) {
var p = args[id];
if(id == "def") {
options[id] = p;
} else {
options[id] = p[0];
}
}
}
var width = isNaN(params[1]) ? false : parseInt(params[1], 10);
var height = isNaN(params[2]) ? false : parseInt(params[2], 10);
options.width = macro.lookupArgument(options, "width", width);
options.height = macro.lookupArgument(options, "height", height);
options.preserveAspectRatio = args.preserveAspectRatio &&
args.preserveAspectRatio[0] == "yes" ? true : false;
options.tiddlyLink = macro.lookupArgument(options, "tiddlyLink", false);
options.link = macro.lookupArgument(options, "link", false);
return options;
},
lookupArgument: function(args, id, ifEmpty) {
return args[id] ? args[id] : ifEmpty;
}
};
// update views
var _oldwikifiedview = config.macros.view.views.wikified;
// update wikifier to check tiddler type before rendering
merge(config.macros.view.views, {
wikified: function(value, place, params, wikifier, paramString, tiddler) {
if(macro.isImageTiddler(tiddler) && params[0] == "text") {
var newplace = $("<div />").addClass("wikifiedImage").appendTo(place)[0];
macro.renderImage(newplace, tiddler.title, { alt: macro.locale.badImage });
} else {
_oldwikifiedview.apply(this, arguments);
}
},
image: function(value, place, params, wikifier, paramString, tiddler) {
// a field can point to another tiddler whereas text is the current tiddler.
var title = params[0] == "text" ? tiddler.title : value;
var args = macro.getArguments(paramString, params);
macro.renderImage(place, title, args);
}
});
config.shadowTiddlers.StyleSheetImageMacro = [".wikifiedImage svg, .wikifiedImage .image { width: 80%; }",
".svgImageText { background-color:[[ColorPalette::Error]]; color:#ddd; display: inline-block; }",
"span.svgImageText { display: inline-block; overflow: hidden; }"
].join("");
store.addNotification("StyleSheetImageMacro", refreshStyles);
})(jQuery);
//}}}
/*{{{*/
Name:DarkerBlue
Background: #e3eaf2
Foreground: #0c141b
PrimaryPale: #ffffff
PrimaryLight: #adc3d9
PrimaryMid: #456688
PrimaryDark: #0a0f15
SecondaryPale: #ffffff
SecondaryLight: #bed9ad
SecondaryMid: #7eb35b
SecondaryDark: #223219
TertiaryPale: #ffffff
TertiaryLight: #d9adc7
TertiaryMid: #b35b90
TertiaryDark: #321928
Error: #f88
/*}}}*/
! How Do You Get Information About Followers
If you want to follow a ~TiddlySpace member, you need to create a tiddler eg: [[@pmario]] and tag it "follow". In addition to this settings, I copy the following line into this tiddler.
{{{
<<tiddler FollowTemplate>>
}}}
This creates a nice overview. The FollowTemplate only works, if you set the {{{evaluateMacroParameters}}} to "full" in eg: [[zzConfig]] tiddler.
{{{
// A temporary hack, to activate transclusions again
config.evaluateMacroParameters = "full";
}}}
!!!! FollowTemplate Content
{{{
{{dp50{Following: <<following {{tiddler.title.split('@')[1]}}>> }}}{{dp50{Followers: <<followers {{tiddler.title.split('@')[1]}}>> }}}
}}}
!!!! FollowTemplate StyleSheet
To get propper site icons you'll need to adjust the {{{.spaceName .siteIcon}}} display CSS in your StyleSheet. Just add the following lines and do a browser reload.
/*{{{*/
.spaceName .siteIcon {
display: inline;
}
/*}}}*/
in reply to:
<<<
The @following space now supports TiddlySpaceIntraSpaceInclusion via the [[TiddlySpaceIntraSpaceInclusion]]@following
This means you can use
{{{
<<tiddler "[[Intraspace Transclusion]]@jon">>
}}}
to transclude content from other spaces.
<<<
This is really fascinating stuff. But it seems to bypass the sanitizer.
{{{
<<tiddler "[[testHTMLsanitize]]@pmbm">>
}}}
The following "click me" button shouldn't work!
<<<
<<tiddler "[[testHTMLsanitize]]@pmbm">>
<<<
/***
|Uglify|http://marijnhaverbeke.nl/uglifyjs|
|Old version:|3344 bytes |
|New version:|759 bytes |
|Saved:|2585 (result is 22.6% of original) |
* A minified version at least should have some license info.
***/
//{{{
(function(a){var b="fancyStyleSheet",c=[".myClass {","\tfont-size: 0.9em;\t/* Some info for the user, why the developer did it that way */","}"];config.shadowTiddlers[b]="/*{{{*/\n"+c.join("\n")+"\n/*}}}*/",store.addNotification(b,refreshStyles);var d=[".myClass {","\tfont-size: 0.9em;","}"];config.shadowTiddlers.myFancyStyleSheet="/*{{{*/\n"+d.join("\n")+"\n/*}}}*/",store.addNotification("myFancyStyleSheet",refreshStyles),config.shadowTiddlers.myFancyStyleSheet_="/*{{{*/\n"+[".myClass {","\tfont-size: 0.9em;","}"].join("\n")+"\n/*}}}*/",store.addNotification("myFancyStyleSheet_",refreshStyles),config.shadowTiddlers.StyleSheetMyPlugin="/*{{{*/\n.myClass {\n\tfont-size: 0.9em;\n}\n/*}}}*/",store.addNotification("StyleSheetMyPlugin",refreshStyles)})()
//}}}
In reply to jon's and ben's [[CloneTiddler is confusing]]@jon
Some time ago I posted some "Thoughts about cloning" at [[DropPrivs In My Way]]@pmario
<<<
!!!Thoughts about cloning
I think, the biggest problem newbie users have, with "cloning"/"editing" is, that there is no visual difference between the edit and clone icon. So they are not aware, that a different action occures.
For all included tiddlers, tagged systemConfig, there should be an additional save dialog, that points out, that there will be no automatic update anymore, if they save a system tiddler locally. This dialog also should pup up, if you save as a role eg: "editor" to an included space.
<<<
''it seems, it's not just newbies.''
!!!Some points made in google group
I also tried to make some of my points clearer at [[issues with tiddlyspace cloning |http://groups.google.com/group/tiddlyweb/browse_thread/thread/9b071b380b341b5f]] started by cdent.
/*{{{*/
* html .tiddler {height:1%;}
body {margin:0; padding:0;}
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}
hr {height:1px;}
a {text-decoration:none;}
dt {font-weight:bold;}
ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}
.txtOptionInput {width:11em;}
#contentWrapper .chkOptionInput {border:0;}
.externalLink {text-decoration:underline;}
.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}
.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}
/* #sidebarOptions {padding-top:0.3em;} */
/* #sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;} */
/* #sidebarOptions input {margin:0.4em 0.5em;} */
/* #sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;} */
/* #sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;} */
/* #sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;} */
/* #sidebarTabs .tabContents {width:15em; overflow:hidden;} */
.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}
.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}
.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}
#contentWrapper {display:block;}
#splashScreen {display:none;}
.toolbar {text-align:right; font-size:.9em;}
/*.tiddler {padding:1em 1em 0;}*/
.missing .viewer,.missing .title {font-style:italic;}
.title {font-size:1.6em; font-weight:bold;}
.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}
.tiddler .button {padding:0.2em 0.4em;}
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}
.footer {font-size:.9em;}
.footer li {display:inline;}
.annotation {padding:0.5em; margin:0.5em;}
* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}
.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
.sparkline {line-height:1em;}
.sparktick {outline:0;}
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}
* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
|''Name''|SvgEvent_Menue|
|''Description''|contains the global TW jQuery custom events.|
|''Author''|Mario Pietsch|
|''Version''|0.2.1|
|''Status''|''stable''|
|''Source''|http://fxplugins.tiddlyspace.com|
|''CoreVersion''|2.6|
|''Documentation''|[[SvgEvent_Info]]|
|''Keywords''|svg, events, animation, commands|
!Important
!Known issues
!History
*V 0.2.1
**stable
**[[SvgEvent_Info]] has more info now
*Version: 0.2.0
**changed function names. They are not ugly anymore :)
**SvgEventzPlugin is not needed anymore!
*Version: 0.1.0
**initial release
!Code
***/
/*{{{*/
if(!version.extensions.SvgEvent_Menue) { //# ensure that the plugin is only installed once
version.extensions.SvgEvent_Menue= { installed: true };
(function($) {
var eventTypes = ["cCloseAll", "cPermaview", "cNewTiddler", "cNewJournal", "cSaveChanges", "cReadDoc", "cmd99"];
menue= {
// if you add event types here. Also go to the end and adjust "var eventTypes" accordingly.
//menueCloseAll
cCloseAll: function(e, trial) {
if (! trial.comp.menue) return false;
story.closeAllTiddlers();
return false;
},
//menuePermaview
cPermaview: function(e, trial) {
if (! trial.comp.menue) return false;
story.permaView();
return false;
},
//menueNewTiddler
cNewTiddler: function(e, trial) {
if (! trial.comp.menue) return false;
// trigger readOnly
if (readOnly) {$(document).trigger('cmd99', trial); return false;}
var title = 'New Tiddler';
story.displayTiddler(null, title);
config.commands.editTiddler.handler(null, null, title);
return false;
},
//menueNewJournal
cNewJournal: function(e, trial) {
if (! trial.comp.menue) return false;
// trigger readOnly
if (readOnly) {$(document).trigger('cmd99', trial); return false;}
var title = config.macros.timeline.dateFormat;
title = new Date().formatString(title.trim());
story.displayTiddler(null, title);
config.commands.editTiddler.handler(null, null, title);
return false;
},
// menueSaveChanges
cSaveChanges: function(e, trial) {
if (! trial.comp.menue) return false;
// trigger readOnly
if (readOnly) {$(document).trigger('cmd99', trial); return false;}
saveChanges();
return false;
},
cReadDoc: function(e, trial) {
if (! trial.comp.menue) return false;
var rdDocMsg= "Read the documentation!";
displayMessage(rdDocMsg);
return false;
},
cmd99: function(e, trial) {
var rdOnlyMsg= "System is readOnly!";
if (! trial.comp.menue) return false;
displayMessage(rdOnlyMsg);
trial.elem.setAttribute('opacity', 0.3);
return false;
}
}; // menue
// if you add components here a
var components = [menue];
$.each(components, function(i,component) {
$.each(eventTypes, function(j,eventType) {
var handler = component[eventType];
if (handler) $(document).bind(eventType, handler);
});
});
})(jQuery);
} //# end of "install only once"
/*}}}*/
--You need to visit [[my space|http://pmario.tiddlyspace.com/#[[Test the Meta Intra Transcluder%5d%5d]], that it works.--
----
{{{
<<tiddler "[[MetaIntraTranscluder]]@greenenergy">>
}}}
<<tiddler "[[MetaIntraTranscluder]]@greenenergy">>
!Discussion
In [[Feedback for Test the Meta Intra Transcluder]]@jon ~@jon says:
<<<
In reply to [[Test the Meta Intra Transcluder]]@pmario (revision [[461510|http://tiddlyspace.com/bags/pmario_public/tiddlers/Test%20the%20Meta%20Intra%20Transcluder/revisions/461510]])
<<<
* IMO The revision link isn't very usefull, since TiddlySpace doesn't take care of it. If you click the link "461510" you'll see what I mean.
----
2011.07.18
At: [[Feedback for Test the Meta Intra Transcluder]]@jon Jon says. that the revision link is to only way to keep track of a conversation. The problem is, that the TiddlySpace "make public" and "make private" doesn't take care of revisions. They are deleted. It doesn't make sense, until this is fixed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#CC9900" offset="0"/>
<stop id="stop2" stop-color="#E8D18B" offset="0.66462"/>
<stop id="stop3" stop-color="#CC9900" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4">
<path id="path3640" style="stroke-dasharray:none;" d="m21.877,50.312,0,14.926" stroke-width="2.50369096" fill="none"/>
<rect id="rect3642" style="stroke-dasharray:none;" transform="matrix(0.707107, -0.707107, 0.707107, 0.707107, 0, 0)" ry="0" height="2.1305" width="2.1305" y="59.855" x="-17.174" stroke-width="2.4" fill="none"/>
<rect id="rect3644" ry="0" style="stroke-dasharray:none;" transform="matrix(0.707107, -0.707107, 0.707107, 0.707107, 0, 0)" height="2.1305" width="2.1305" y="66.038" x="-23.357" stroke-width="2.4" fill="none"/>
<path id="path3646" style="stroke-dasharray:none;" d="m22.664,54.557,3.0416,0" stroke-width="2.4" fill="none"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
<<tiddler FollowTemplate>>
<<tiddler TwitterCardsTwitterDevelopers>>
<<tiddler FollowTemplate>>
Triggered by: HowDoISocialInTiddlySpace@jrbl
The following may answere some of jrbl's questions, but mainly it reflects my opinion and some thoughts.
* --Since jrbl doesn't follow me (until now: 2011.03.31), he'll probably miss it :)--
* This is one of the biggest disadvantages, TiddlySpace-following mechanism introduces. You have to dig deep into the sytem to get it's power. But imo it is there, just the UI is missing.
** I use tsScanByTag@pmario which gives a nice overview. I like this type of aggregation, because I can decide what is shown and how.
* Contrary to cdent's TiddlySpaceTips@cdent I don't use feed readers, with TiddlySpace.
** Using external stuff, doesn't point out the difficulties, that arise using TS.
** IMO without these issues, there would be no further development.
** Jeremy once said: {{{ยซWe should eat our own dog food.ยป}}} I'd say: "It's quite nice :)"
* Transcluding an alien tiddler is a nice idea.
* I do have a mechanism, that "transcludes" tagged tiddlers See my ~ViewTemplate section at: NeUIemTheme@pmario
** It uses the showWhenTagged macro known from MPTW TW.
** tsScan macro with a TEMPLATE@pmario is used to display the alien content.
** My tiddler needs to be tagged "topic". See http://pmario.tiddlyspace.com/#HowDoISocialInTiddlySpace
** (Having a look at this topic, I really should adjust the CSS or make them sliders :)
<<<
<!--{{{-->
<div class='viewer' macro='showWhenTagged topic'>
<h1>Others say</h1>
<div macro='tsScan {{tiddler.title}} fat:y template:"TEMPLATES##scanComment" query:"select=modifier:!pmario" '></div>
</div>
<!--}}}-->
<<<
* To see, who follows whom, who follows me and who I follow, I use FollowTemplate@pmario, which is included in every tiddler, that is tagged "follow". see: http://pmario.tiddlyspace.com/#@jrbl
** Lately there sometimes is a view macro error. I need to check this (someday)
** Since I use TagglyTagging, there is a nice list of all tiddlers tagged eg: {{{@jrbl}}}, that I've written.
** No searching, no nothing - It just works.
* Filtering by user, can be done, but needs some more tricks and probably doesn't work for every usecase.
** I use 2 tsScan macros with some templating.
** See {{{News@news}}} News@news or goto: [[News space|http://news.tiddlyspace.com/]] where I have multi colum view.
** (There should be dnd layout editing in the future, with the help of list macro. Some more testing will be needed :)
** (I have an idea, how to implement voting per tiddler to tiddlyspace, but this needs some more tsScan testing.)
* Easy UI for moving tiddlers around spaces would be really nice.
* Having SaaS macros in TS is called "space inclusion". The downside is, that you include everything. That's why some spaces need a so called "presentation space" that contains the documentation and examples and a "-plugin" space, that only contains one/more plugins. Lately I name all my plugin spaces xx-plugin and the presentation spaces get a different name. But this doesn't make it easier for the user.
* I'd love to have a mechanism, that lets me have several macros in one space and include them per tiddler. But this seems to be not that easy. And cdent pointed it out several times allready.
** Especially the @piwik space would benefit from this type of inclusion.
** I have some ideas about it, but didn't dig into it yet.
* Offline/Online Syncing is ''the'' main reason, why I joined TiddlyWiki.
** I have posted to [[TiddlyWeb group|http://groups.google.com/group/tiddlyweb/msg/db23cd90d1128a02?hl=en]] some time ago. Mainly to become clearer, what I expect from a TS sync mechanism. I use it to test the various iterations of the existing sync against it.
** I am not satisfied yet and expressed it at the TWeb group: [[Broken Tiddly Space offline workflow|http://groups.google.com/group/tiddlywikidev/browse_thread/thread/88d68d0c183d1c28]]
BUT .. I have to say, we are whining on a high level allready ;)
have fun!
/*{{{*/
Name: MpBlue
Background: #ffd
Foreground: #000
PrimaryPale: #ccd
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
(function() {
var getCSRFToken = function(window) {
// XXX: should not use RegEx - cf.
// http://www.quirksmode.org/js/cookies.html
// https://github.com/TiddlySpace/tiddlyspace/commit/5f4adbe009ed4bda3ce39058a3fb07de1420358d
var regex = /^(?:.*; )?csrf_token=([^(;|$)]*)(?:;|$)/;
var match = regex.exec(document.cookie);
var csrf_token = null;
if (match && (match.length === 2)) {
csrf_token = match[1];
}
return csrf_token;
};
if (typeof config !== 'undefined' && config.extensions &&
config.extensions.tiddlyspace &&
config.extensions.tiddlyspace.getCSRFToken === null) {
config.extensions.tiddlyspace.getCSRFToken = getCSRFToken;
} else {
window.getCSRFToken = getCSRFToken;
}
})(window);
Let's talk about frameworks and IDEs. There are a bunch of them. There are big ones. There are small ones. Most of them are pretty cool!
!! The Big Ones
* [[jQuery|http://jquery.com/]]
* [[jQueryUI|http://jqueryui.com/]]
* [[dojo|http://dojotoolkit.org/]]
* [[commonjs|http://www.commonjs.org/]]
!! The small ones
* http://microjs.com/
** A lot of them :)
!! The phone ones
* [[XUI|http://xuijs.com/]]
* [[jQTouch|http://jqtouch.com]]
* [[Jo|http://joapp.com]]
* [[Sencha Touch|http://sencha.com]]
* [[jQueryMobile|http://jquerymobile.com/]]
* [[zeptojs|http://zeptojs.com]]
!! The Relax ones
* [[kansojs|http://kansojs.org]] - I really like this approach.
* [[couchapp|http://couchapp.org]]
!! The Native App Generators
* [[PhoneGap|http://www.phonegap.com/]]
* [[Titanium|http://www.appcelerator.com/products/]]
!! The IDEs
* [[Cloud9 IDE|http://cloud9ide.com/]]
* [[Maqetta|http://maqetta.org/]]
!! The Tools
* [[jsFiddle|http://jsfiddle.net/]]
* [[LawnChair|http://westcoastlogic.com/lawnchair/]]
!! The NodeJs ones
* [[NodeJs Modules|https://github.com/joyent/node/wiki/modules]]
!! And a hell lot of others, that are AddOns for the above.
''But .. They have one thing in common. They are for developers.''
''TW should be for endusers. This makes it unique.''
! TW is all of them - but older
* I like the "A Tiddler is a Tiddler is a Tiddler" approach
** A plugin is just content.
** A ~PageTemplate is just content.
** It's all just content.
** It's all tiddlers.
! My Point of View
* IMO it isn't a problem, of seperating code from content. This can be achieved with existing TW too. If a TW App developer just makes the right configurations.
* "Create your own" empty TW, based on an existing one, needs to be improved.
* TiddlyWiki is a "grown" application, that started existing long before one of the above, was even thought of. And so, it contains some "bad parts".
* ''IMO "macros are tiddlers" are the "good parts".''
There are some related comments at [[SideBarOptions in the Backstage]]@pmario.
To sum it up:
* It should be there for TS management tasks.
* It should be there, if I mess up my space.
* The rest of the day, it's closed.
* I even don't use the "new" search function, because I don't think about it.
~@tobias: Skype?
----
----
~@tobias I have some ideas, to include it as a real toolbar command. TiddlySpace core would do the rest. If we could talk/skype a little bit, I think communication would be much faster :)
-m
----
----
2010.10.01
in reply to @tobibeer:
<<<
I would love to use a custom svg for buttons that are not part of the default ToolbarCommands. How would I do that?
Check out the icons in [[my space|Welcome]]@tobibeer ...pure css and default icons. Now how would I give that TagSearchPlugin button a lovely bookmark?
<<<
I thought allready about this. But I wasn't clear how to nicely implement it. There is a new "hijack" possibility with toolbar commands handler, which was introduced with 2.6.1 core. I think I'll have a closer look about this function.
I also thought about the new security mechanisms, which will be also used for event functions inside svg. Which will be a "problem" for my javascript custom event system with svg buttons.
{{dp50{Following: <<following {{tiddler.title.split('@')[1]}}>> }}}{{dp50{Followers: <<followers {{tiddler.title.split('@')[1]}}>> }}}
<<slider chkSliderOptionsPanel OptionsPanel "Options ยป" "display the options panel">>
/***
|''Name:''|TiddlySpaceIntraSpaceInclusion|
|''Description:''|Provides support for {{{<<tiddler Foo@bar>>}}} and {{{<<tiddler [[Foo]]@bar>>}}}|
|''Author:''|Jon Robson|
|''Source:''|https://github.com/jdlrobson/TiddlyWikiPlugins/raw/master/plugins/TiddlySpaceIntraSpaceInclusion/TiddlySpaceIntraSpaceInclusion.js|
|''Version:''|0.3.8a|
|''License:''|[[BSD License|http://www.opensource.org/licenses/bsd-license.php]] |
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''~CoreVersion:''|2.4|
***/
//{{{
(function() {
var _tidtext = TiddlyWiki.prototype.getTiddlerText;
var cache = {};
// allmost the same regExp as in TiddlySpaceLinkPlugin but .. no "mg" parameter, because it didn't work for this usecase.
config.textPrimitives.spacenameLinkRegExp = new RegExp(config.textPrimitives.unWikiLink +
"?(" + config.textPrimitives.bareTiddlerLetter + "*)@(" + config.textPrimitives.spaceName + ")", "");
config.textPrimitives.tiddlyLinkSpacenameLinkRegExp = new RegExp("\\[\\[(.*?)(?:\\|(.*?))?\\]\\]@(" + config.textPrimitives.spaceName + ")", "");
TiddlyWiki.prototype.getTiddlerText = function(title, defaultText) {
var ct = config.textPrimitives;
var match = ct.spacenameLinkRegExp.exec(title); // foo@bar
var match2 = ct.tiddlyLinkSpacenameLinkRegExp.exec(title); // [[foo]]@bar
if(match || match2) {
// console.log('inner: ', 'spacename: ', match, 'tiddlyLink: ', match2, 'place: ');
var tidtitle, space;
if(match[1] && match.length === 3) {
tidtitle = match[1];
space = match[2];
} else if(match2 && match2.length === 4) {
tidtitle = match2[1];
space = match2[3];
}
var newtitle = tidtitle + "@" + space;
if(tidtitle && space) {
title = newtitle;
}
if(tidtitle && space && !store.getTiddler(newtitle)) {
var tiddler = new Tiddler(title);
// get the tiddler, where the macro is rendered. //XXX will need more testing
var el = story.findContainingTiddler(place);
var refreshTitle = (el) ? el.getAttribute('tiddler') : null;
tiddler.text = "//retrieving from server//";
tiddler.fields.doNotSave = "true";
tiddler.tags = ["excludeLists", "excludeSearch", "excludeMissing"];
merge(tiddler.fields, config.defaultCustomFields);
tiddler.fields["server.bag"] = space + "_public";
tiddler = store.addTiddler(tiddler);
ajaxReq({ url: "/bags/" + space + "_public/tiddlers/" + tidtitle,
dataType: "json",
success: function(tid) {
var tiddler = store.getTiddler(title);
tiddler.text = tid.text;
store.addTiddler(tiddler);
// store.notify(title,true);
story.refreshTiddler(refreshTitle,null,true);
// story.refreshAllTiddlers(); // hacky but above link doesn't always seem to work!
},
error: function() {
var tiddler = store.getTiddler(title);
tiddler.text = "//error retrieving tiddler {{{" + title + "}}} from space @" + space + "//";
store.addTiddler(tiddler);
// store.notify(title,true);
story.refreshTiddler(refreshTitle,null,true);
// story.refreshAllTiddlers(); // hacky but above link doesn't always seem to work!
}
});
}
}
return _tidtext.apply(this, [title, defaultText]);
}
})();
//}}}
/***
Source code at: https://github.com/coreyti/showdown/blob/master/src/showdown.js
***/
///%
var Showdown={extensions:{}};var forEach=Showdown.forEach=function(e,t){if(typeof e.forEach==="function"){e.forEach(t)}else{var n,r=e.length;for(n=0;n<r;n++){t(e[n],n,e)}}};var stdExtName=function(e){return e.replace(/[_-]||\s/g,"").toLowerCase()};Showdown.converter=function(e){var t;var n;var r;var i=0;var s=[];var o=[];if(typeof module!=="undefind"&&typeof exports!=="undefined"&&typeof require!=="undefind"){var u=require("fs");if(u){var a=u.readdirSync((__dirname||".")+"/extensions").filter(function(e){return~e.indexOf(".js")}).map(function(e){return e.replace(/\.js$/,"")});Showdown.forEach(a,function(e){var t=stdExtName(e);Showdown.extensions[t]=require("./extensions/"+e)})}}this.makeHtml=function(e){t={};n={};r=[];e=e.replace(/~/g,"~T");e=e.replace(/\$/g,"~D");e=e.replace(/\r\n/g,"\n");e=e.replace(/\r/g,"\n");e="\n\n"+e+"\n\n";e=F(e);e=e.replace(/^[ \t]+$/mg,"");Showdown.forEach(s,function(t){e=l(t,e)});e=N(e);e=h(e);e=c(e);e=d(e);e=B(e);e=e.replace(/~D/g,"$$");e=e.replace(/~T/g,"~");Showdown.forEach(o,function(t){e=l(t,e)});return e};if(e&&e.extensions){var f=this;Showdown.forEach(e.extensions,function(e){if(typeof e==="string"){e=Showdown.extensions[stdExtName(e)]}if(typeof e==="function"){Showdown.forEach(e(f),function(e){if(e.type){if(e.type==="language"||e.type==="lang"){s.push(e)}else if(e.type==="output"||e.type==="html"){o.push(e)}}else{o.push(e)}})}else{throw"Extension '"+e+"' could not be loaded. It was either not found or is not a valid extension."}})}var l=function(e,t){if(e.regex){var n=new RegExp(e.regex,"g");return t.replace(n,e.replace)}else if(e.filter){return e.filter(t)}};var c=function(e){e+="~0";e=e.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,function(e,r,i,s,o){r=r.toLowerCase();t[r]=_(i);if(s){return s+o}else if(o){n[r]=o.replace(/"/g,"")}return""});e=e.replace(/~0/,"");return e};var h=function(e){e=e.replace(/\n/g,"\n\n");var t="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside";var n="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";e=e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,p);e=e.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,p);e=e.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,p);e=e.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,p);e=e.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,p);e=e.replace(/\n\n/g,"\n");return e};var p=function(e,t){var n=t;n=n.replace(/\n\n/g,"\n");n=n.replace(/^\n/,"");n=n.replace(/\n+$/g,"");n="\n\n~K"+(r.push(n)-1)+"K\n\n";return n};var d=function(e){e=E(e);var t=C("<hr />");e=e.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,t);e=e.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,t);e=e.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,t);e=x(e);e=T(e);e=O(e);e=h(e);e=M(e);return e};var v=function(e){e=k(e);e=m(e);e=D(e);e=b(e);e=g(e);e=P(e);e=_(e);e=A(e);e=e.replace(/ +\n/g," <br />\n");return e};var m=function(e){var t=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;e=e.replace(t,function(e){var t=e.replace(/(.)<\/?code>(?=.)/g,"$1`");t=I(t,"\\`*_");return t});return e};var g=function(e){e=e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,y);e=e.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,y);e=e.replace(/(\[([^\[\]]+)\])()()()()()/g,y);return e};var y=function(e,r,i,s,o,u,a,f){if(f==undefined)f="";var l=r;var c=i;var h=s.toLowerCase();var p=o;var d=f;if(p==""){if(h==""){h=c.toLowerCase().replace(/ ?\n/g," ")}p="#"+h;if(t[h]!=undefined){p=t[h];if(n[h]!=undefined){d=n[h]}}else{if(l.search(/\(\s*\)$/m)>-1){p=""}else{return l}}}p=I(p,"*_");var v='<a href="'+p+'"';if(d!=""){d=d.replace(/"/g,"");d=I(d,"*_");v+=' title="'+d+'"'}v+=">"+c+"</a>";return v};var b=function(e){e=e.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,w);e=e.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,w);return e};var w=function(e,r,i,s,o,u,a,f){var l=r;var c=i;var h=s.toLowerCase();var p=o;var d=f;if(!d)d="";if(p==""){if(h==""){h=c.toLowerCase().replace(/ ?\n/g," ")}p="#"+h;if(t[h]!=undefined){p=t[h];if(n[h]!=undefined){d=n[h]}}else{return l}}c=c.replace(/"/g,"");p=I(p,"*_");var v='<img src="'+p+'" alt="'+c+'"';d=d.replace(/"/g,"");d=I(d,"*_");v+=' title="'+d+'"';v+=" />";return v};var E=function(e){function t(e){return e.replace(/[^\w]/g,"").toLowerCase()}e=e.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(e,n){return C('<h1 id="'+t(n)+'">'+v(n)+"</h1>")});e=e.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(e,n){return C('<h2 id="'+t(n)+'">'+v(n)+"</h2>")});e=e.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(e,n,r){var i=n.length;return C("<h"+i+' id="'+t(r)+'">'+v(r)+"</h"+i+">")});return e};var S;var x=function(e){e+="~0";var t=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;if(i){e=e.replace(t,function(e,t,n){var r=t;var i=n.search(/[*+-]/g)>-1?"ul":"ol";r=r.replace(/\n{2,}/g,"\n\n\n");var s=S(r);s=s.replace(/\s+$/,"");s="<"+i+">"+s+"</"+i+">\n";return s})}else{t=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;e=e.replace(t,function(e,t,n,r){var i=t;var s=n;var o=r.search(/[*+-]/g)>-1?"ul":"ol";var s=s.replace(/\n{2,}/g,"\n\n\n");var u=S(s);u=i+"<"+o+">\n"+u+"</"+o+">\n";return u})}e=e.replace(/~0/,"");return e};S=function(e){i++;e=e.replace(/\n{2,}$/,"\n");e+="~0";e=e.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(e,t,n,r,i){var s=i;var o=t;var u=n;if(o||s.search(/\n{2,}/)>-1){s=d(j(s))}else{s=x(j(s));s=s.replace(/\n$/,"");s=v(s)}return"<li>"+s+"</li>\n"});e=e.replace(/~0/g,"");i--;return e};var T=function(e){e+="~0";e=e.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(e,t,n){var r=t;var i=n;r=L(j(r));r=F(r);r=r.replace(/^\n+/g,"");r=r.replace(/\n+$/g,"");r="<pre><code>"+r+"\n</code></pre>";return C(r)+i});e=e.replace(/~0/,"");return e};var N=function(e){e+="~0";e=e.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(e,t,n){var r=t;var i=n;i=L(i);i=F(i);i=i.replace(/^\n+/g,"");i=i.replace(/\n+$/g,"");i="<pre><code"+(r?' class="'+r+'"':"")+">"+i+"\n</code></pre>";return C(i)});e=e.replace(/~0/,"");return e};var C=function(e){e=e.replace(/(^\n+|\n+$)/g,"");return"\n\n~K"+(r.push(e)-1)+"K\n\n"};var k=function(e){e=e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,t,n,r,i){var s=r;s=s.replace(/^([ \t]*)/g,"");s=s.replace(/[ \t]*$/g,"");s=L(s);return t+"<code>"+s+"</code>"});return e};var L=function(e){e=e.replace(/&/g,"&");e=e.replace(/</g,"<");e=e.replace(/>/g,">");e=I(e,"*_{}[]\\",false);return e};var A=function(e){e=e.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>");e=e.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");return e};var O=function(e){e=e.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(e,t){var n=t;n=n.replace(/^[ \t]*>[ \t]?/gm,"~0");n=n.replace(/~0/g,"");n=n.replace(/^[ \t]+$/gm,"");n=d(n);n=n.replace(/(^|\n)/g,"$1 ");n=n.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(e,t){var n=t;n=n.replace(/^ /mg,"~0");n=n.replace(/~0/g,"");return n});return C("<blockquote>\n"+n+"\n</blockquote>")});return e};var M=function(e){e=e.replace(/^\n+/g,"");e=e.replace(/\n+$/g,"");var t=e.split(/\n{2,}/g);var n=[];var i=t.length;for(var s=0;s<i;s++){var o=t[s];if(o.search(/~K(\d+)K/g)>=0){n.push(o)}else if(o.search(/\S/)>=0){o=v(o);o=o.replace(/^([ \t]*)/g,"<p>");o+="</p>";n.push(o)}}i=n.length;for(var s=0;s<i;s++){while(n[s].search(/~K(\d+)K/)>=0){var u=r[RegExp.$1];u=u.replace(/\$/g,"$$$$");n[s]=n[s].replace(/~K\d+K/,u)}}return n.join("\n\n")};var _=function(e){e=e.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&");e=e.replace(/<(?![a-z\/?\$!])/gi,"<");return e};var D=function(e){e=e.replace(/\\(\\)/g,q);e=e.replace(/\\([`*_{}\[\]()>#+-.!])/g,q);return e};var P=function(e){e=e.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>');e=e.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(e,t){return H(B(t))});return e};var H=function(e){var t=[function(e){return"&#"+e.charCodeAt(0)+";"},function(e){return"&#x"+e.charCodeAt(0).toString(16)+";"},function(e){return e}];e="mailto:"+e;e=e.replace(/./g,function(e){if(e=="@"){e=t[Math.floor(Math.random()*2)](e)}else if(e!=":"){var n=Math.random();e=n>.9?t[2](e):n>.45?t[1](e):t[0](e)}return e});e='<a href="'+e+'">'+e+"</a>";e=e.replace(/">.+:/g,'">');return e};var B=function(e){e=e.replace(/~E(\d+)E/g,function(e,t){var n=parseInt(t);return String.fromCharCode(n)});return e};var j=function(e){e=e.replace(/^(\t|[ ]{1,4})/gm,"~0");e=e.replace(/~0/g,"");return e};var F=function(e){e=e.replace(/\t(?=\t)/g," ");e=e.replace(/\t/g,"~A~B");e=e.replace(/~B(.+?)~A/g,function(e,t,n){var r=t;var i=4-r.length%4;for(var s=0;s<i;s++)r+=" ";return r});e=e.replace(/~A/g," ");e=e.replace(/~B/g,"");return e};var I=function(e,t,n){var r="(["+t.replace(/([\[\]\\])/g,"\\$1")+"])";if(n){r="\\\\"+r}var i=new RegExp(r,"g");e=e.replace(i,q);return e};var q=function(e,t){var n=t.charCodeAt(0);return"~E"+n+"E"}};if(typeof module!=="undefined")module.exports=Showdown;if(typeof define==="function"&&define.amd){define("showdown",function(){return Showdown})}
// %/
<<list filter [tag[topic]][sort[-modified]]>>
<<tiddler FollowTemplate>>
If you need a different background color goto: http://pmario.tiddlyspace.com
I think teamtasks gets its beauty from the color scheme. The dark search area and the dark title. And there definitely is a sidebar on the left. Browser text zooming doesn't break the layout. Which is nice.
In my opinion also carbon-calculator uses a good color scheme. The layout is nice. But on a "small" 16" screen, with high resolution (1920x1080) the default text size is way to small. So zooming is needed, which breaks the absolut layout. see the pics [1][2].
I know, that the readability of text, is bad, if there are too many words/chars in one line. But for my taste, on my laptop at jon's space, there is too much white space. see [3]. Zooming doesn't help there.
I like Jeremy's approach for TW5. Where you have a 3 column layout. What I'd like for a prose space, is a layout similar to a newspaper.
*I use Recent tab a lot. Full length.
*I like Spaces, because it gives overview, where things come from. And exclude?? isn't applyed.
*I sometimes use Public, Private, Following, Followers
**If there are more then 3-4 tiddlers in Private, I go to the backstage to publish them.
*Tags is used to get the exclude?? stuff.
*I haven't ever used
** All (because All means absolutely everything. Which isn't true in this case.)
** Orphans
** Missing
*** Missing at tiddlyspace imo makes no sense. Since my missing: "AsAWiki" at the moment comes from cdent (a sucked in tiddler). Some missing tiddlers may come from included spaces. If the space is excluded, these tiddlers may be Orphans ?!?
** Drafts
** Activity (Is a TopMenu item)
For work in progress spaces, for me it's important, to have fast access to "everything". So opening backstage is painfull allready ;)
For searching I use GotoPlugin and SearchOptionsPlugin. If a space hasn't installed propper search, I dynamically load YourSearch plugin from the bookmarks.
I think Alex Hough somewhere talked about "the unknown unknown". Which happens, if too much functionality is hidden by default, and if there is too less documentation.
[1]<<image "http://img2.imagebanana.com/img/2yh61w3m/thumb/CarbonFootprint01.png" link:"http://www.imagebanana.com/view/2yh61w3m/CarbonFootprint01.png">> [2]<<image "http://img2.imagebanana.com/img/8kuexzv9/thumb/CarbonFootprint02.png" link:"http://www.imagebanana.com/view/8kuexzv9/CarbonFootprint02.png">>
[3]<<image "http://img2.imagebanana.com/img/ra9bs6p3/thumb/Bildschirmfoto.png" link:"http://www.imagebanana.com/view/ra9bs6p3/Bildschirmfoto.png">>
!Others say
<<tsScan [[The Sidebar is overrated]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
! Tiddlers, Recipes and Bags
Some definitions are taken from [[TiddlyWeb technical documentation|http://tiddlyweb.peermore.com/wiki/#recipe%20bag%20tiddler]], but skipping the technical stuff :)
!! Tiddler
>A Tiddler is the ''fundamental piece of content'' in a TiddlyWiki.
!! Recipe
>A recipe is an ordered list of bags and filters that generates a ''list of tiddlers''.
!! Bag
>A bag is a ''container of uniquely named tiddlers''. A bag can have rules for who can edit, delete or read the tiddlers in the bag. These rules are defined in a policy.
!! What does this mean for ~TiddlySpace?
* When you create an account at TiddlySpace.com, you basically create a recipe (a build instruction for the web server), which is bound to your space name and your password.
* Since a ~TiddlySpace TW, needs some additional plugins, to work with the web, this recipe contains some "system-" bags. Namely: {{{system-plugins, system-info, system-images, system-theme}}} and your ''private'' and ''public'' bags.
!!! The {{{pmario}}} Recipe
My space name is "pmario" (pmario.tiddlyspace.com) The basic recipe for this space looks like this.
recipe: pmario
{{{
bag: system-plugins
bag: system-info
bag: system-images
bag: system-theme
bag: pmario
}}}
You may ask: "And how, can the server decide, what's private and what's public?"
Right!
That's done, with the policies mentioned above. At space creation time the server creates 2 bags: {{{pmario_private and pmario_public}}}. Where the _public is readOnly for everyone. The _private bag can be accessed by pmario (me) only.
recipe: pmario
{{{
bag: system-plugins_public
bag: system-info_public
bag: system-images_public
bag: system-theme_public
bag: pmario_public
bag: pmario_private
}}}
Since I am a member of the pmario space I can see the _public and the _private bags. I'm not a member of the "system-" spaces, so there's the _public stuff only.
!! Bag Cascading
Knowing the above, you may say: "OK, but what if two bags are containg the same tiddler name, eg: GettingStarted"?
Well ... They are overwritten (by intention). You can see the one in the last bag, where you have read access.
{{{
bag: system-plugins_public GettingStarted .. you
bag: system-info_public GettingStarted .. can't
bag: system-images_public GettingStarted .. see those tiddlers
bag: system-theme_public
bag: pmario_public GettingStarted .. you'll see this one
bag: pmario_private
}}}
In this case, it is the {{{pmario_public}}}. If you mark a tiddler as private, it is moved from you public to your private bag. With ~TiddlySpace it turned out, to be usefull in this way.
!! "Shadow tiddlers"
~TiddlyWiki introduces shadow tiddlers. A shadow tiddler is a "hardcoded tiddler" known by the TW core. You can edit it, and it becomes a "normal" tiddler. But you can't delete it. Which is nice. So if you mess up your own "normal" tiddler, you just delete the mess and get the shadow tiddler back.
!! Cloning Tiddler Content
With ~TiddlySpace every tiddler, that is included (see include mechanism !!!!!!!TODO) into your space, behaves very similar to a shadow tiddler. If you edit a tiddler from an included space, it will be physically cloned / copied into your space. The original tiddler is not touched, even if you are the owner.
* To edit an "alien / included" tiddler, it has to be cloned.
* The clone can be private or public.
* ''ATTENTION:'' If a cloned tiddler is private, only members of a space can see them.
** If you are a guest, you'll still see the public tiddler from the included space.
** So you have to be aware, that there may be different views of your space.
** This behaviour is powerfull, but it can be confusing for newbies.
* If you delete a cloned tiddler from your space, the tiddler from the included space will take over again. This behaviour is very similar to shadow tiddlers.
** See ''Bag Cascading'' above.
Ultra Block nesting {{{<code> .. </code>}}}
<<<
<code class="brush:tiddlywiki">
{{{
<!--{{{-->
<code class="brush:tiddlywiki">
! heading
text
{{{ code }}}
< /code>
<!--}}}-->
}}}
</code>
<<<
renders like:
<<<
{{{
<!--{{{-->
<code class="brush:tiddlywiki">
! heading
text
{{{ code }}}
</code>
<!--}}}-->
}}}
<<<
XML renders like:
<<<
<!--{{{-->
<code class="brush:tiddlywiki">
! heading
text
{{{ code }}}
</code>
<!--}}}-->
<<<
TW renders like:
<<<
<code class="brush:tiddlywiki">
! heading
text
{{{ code }}}
</code>
<<<
renders like:
<<<
! heading
text
{{{ code }}}
<<<
/*{{{*/
// Possible Themes:
// "NeUIemTheme", "NeUIemTheme01", "NeUIemTheme02", "NeUIemTheme03", "TWDefaultTheme"
config.options.txtTheme = "NeUIemTheme03"
// New tiddlers a private by default.
config.options.chkPrivateMode = true;
// A temporary hack, to activate transclusions again
config.evaluateMacroParameters = "full";
// remove leading // at the lines below to aktivate left or right sidebar
// config.options.chkShowRightSidebar = false; // false or true
// config.options.chkShowLeftSidebar = false; // false or true
// default config.taggly.config.excludeTags = ["excludeLists","excludeTagging"];
config.taggly.config.excludeTags = ["excludeTagging"];
// Set default tab to OpenId for login
config.options.txtLoginTab = 'OpenID';
/*}}}*/
<!--{{{-->
<div macro='slideRevision'></div>
[[NeUIemTheme##ViewTemplate]]
<!--}}}-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>TiddlySpace Apps</title>
<link rel="stylesheet" href="/bags/common/tiddlers/reset.css" />
<link rel="stylesheet" href="/bags/common/tiddlers/appspage.css" />
<!--[if lt IE 7 ]>
<link rel="stylesheet" href="/bags/common/tiddlers/appspageie6.css" />
<![endif]-->
</head>
<body>
<div id="wrapper">
<div id="TSbar"></div>
<div id="main-content">
<div id="space-details">
<a href="/_space"><img class="siteicon"></a>
<div id="title-subtitle">
<h1 class="spaceaddress">
<span class="spaceName"></span><span class="hostName"></span>
</h1>
<p class="tagline"><span class="subTitle"></span><a class="managespaces" href="/_space">manage space</a></p>
</div>
</div>
<div id="holder">
<div id="appswitcher-wrapper">
<div id="appswitcher">
<h2>Your Apps</h2>
<ul id="app-list">
<li class="htmlserialisation">
<a href="/tiddlers.html?select=tag:!excludeLists;sort=-modified">
<img src="/bags/common/tiddlers/browse_read_blue.png" alt="Icon for the HTML Serialisation" class="app-img" />
BROWSE
</a>
</li>
<li class="tiddlywiki">
<a href="/tiddlers.wiki">
<img src="/bags/common/tiddlers/tiddlywiki2_blue.png" alt="Icon for TiddlyWiki" class="app-img" />
TIDDLYWIKI
</a>
</li>
</ul>
<div id="addapp">
<button class="inactive">Add More!</button>
</div>
</div>
<div id="app-desc">
<ul>
<li class="htmlserialisationdesc"><p>an easy to understand HTML representation of your content.</p></li>
<li class="tiddlywikidesc"><p>use TiddlyWiki to create, edit and organise your content.</p></li>
</ul>
</div>
<div style="clear: both;"></div>
</div>
</div>
</div>
<div id="footer"><!-- ie doesn't support footer tag -->
<div id="footer-content">
<div class="links">
<a href="http://blog.tiddlyspace.com">blog</a>
<a href="http://featured.tiddlyspace.com">featured</a>
<a href="http://docs.tiddlyspace.com">documentation</a>
<a href="https://github.com/TiddlySpace/tiddlyspace">source</a>
</div>
<p>TiddlySpace 2011, created by <a href="http://osmosoft.com">Osmosoft</a></p>
</div>
</div>
</div>
<script type="text/javascript" src="/bags/common/tiddlers/backstage.js"></script>
<script type="text/javascript" src="/bags/common/tiddlers/jquery.js"></script>
<script type="text/javascript" src="/bags/tiddlyspace/tiddlers/chrjs"></script>
<script type="text/javascript" src="/bags/common/tiddlers/chrjs-store.js"></script>
<script type="text/javascript" src="/bags/common/tiddlers/jquery-json.js"></script>
<script type="text/javascript" src="/bags/common/tiddlers/appspage.js"></script>
</body>
</html>
@FreeStyle launched today (2010.11.13)!
*The theme generators are meant for power users.
*Feedbach is very welcome
*Also see: http://groups.google.com/group/tiddlywiki/browse_thread/thread/e50e92060508b26e?hl=en
In reply to [[Interspace Trasclusion]]@cdent @cdent
<<<
* The functionality ought to be replicated in TiddlyWiki.
This latter is interesting as the mechanics for making it happen are considerably more complex than those required with twikifier. The TiddlyWiki will need to make an ajax request to the server to fulfill the need for the remote tiddler. Would the TiddlyWiki cache the results, or remake the request with every {{{refresh}}}? What would happen if the TiddlyWiki were offline?
<<<
There is a functionality like this. TiddlySpaceIntraSpaceInclusion@following at the @following space. It works quite well, even through several spaces.
I did test it at [[Test the Meta Intra Transcluder]]@pmario which transcludes through several spaces. You'll need to dig a bit, to see what happens.
in reply to Tobias at [[The Concertina]]@tobibeer
<<<
... snip ...
But I can surely imagine very viable use-cases... take [[x-tab|http://tbgtd.tiddlyspot.com/#x-tab]] for example (esp. the button in the toolbar).
<<<
agreed
<<<
I would, however, envision [[The Concertina]] not as a one-at-a-time-container to display information triggered by a single plugin but rather allowing a certain ''content stack'' of inner blocks which to close or remove might either be the responsiblity of the plugin or toolbar button that instanciated it or maybe a standard "x" button for each block that provides that ability ...along with another one to close the whole concertina (if there were multiple blocks in it).
<<<
I also like Jeremy's tab idea. It also has the advantage, that tabs don't load everything into the DOM and hide it.
<<<
The benefit of that were that those content blocks might even be used in combination with each other... if one dares to think of such. Imagine a plugin to filter something and another being able to do something with the result list (without having to reinvent the filtering!).
<<<
I'd love to have a behavior like this. See my post at the [[TiddlyWikiDev group|http://groups.google.com/group/tiddlywikidev/browse_thread/thread/9c9f0f5678b49e48/46690014d5e7b6b0]]
----
2010.10.05
----
in reply to Jeremy at [[The Concertina]]@jermolene
<<<
The issue with the concertina was really in relation to using them for the public/private transitions.
<<<
I don't like the popup. Neither for the following info button, nor for p/p transition. And I don't like, that there are different methods/positions to change a tiddlers state. The good thing is, that tw has the possibility to change it :)
<<<
I agree that as a general UI thing it's still pretty useful for the reasons noted. There was something similar in the TiddlyWiki5 prototype:
http://tiddlywiki.com/tiddlywiki5
(click on the "//i//" icon to see the concertina)
<<<
Is there some development going on with TW5?
<<<
One way to implement the concertina that's more inline with classic TiddlyWiki would be to think of it as the ability to nominate certain tiddler toolbar commands to be tabs that slide open to show their controls, instead of using popups as at present.
For instance, in my ToolbarCommands tiddler, I could define something like:
{{{
|~ViewToolbar|+editTiddler +cloneTiddler > (fields) changeToPublic changeToPrivate (revisions) (syncing) permalink references jump closeOthers < closeTiddler|
|~EditToolbar|+saveTiddler saveDraft -cancelTiddler deleteTiddler|
|~RevisionToolbar|> fields revert|
}}}
The commands in parenthesis would be displayed as tabs instead of popups. Once opened, a tab would be closed by opening a different one, or re-clicking on the original one.
<<<
This is a quite interesting idea.
----
----
2010.10.05
in reply to @jon:
<<<
The concertina was currently not judged as fitting in with a default TiddlySpace as it was part of the UI new users would have to discover. However it's missed according to [[The Concertina]]@pmario
<<<
hmm. I followed its silent death. But in my opinion it is something like an easter egg. I like it.
<<<
This doesn't mean it's gone forever and may have uses elsewhere. I have setup the @concertina space to allow plugin developers to make use of it for other macros / existing macros. What is annoying about the concertina is the macros that use it have to be aware of its existence. @pmario I have added you to the space so feel free to provide a better implementation of what is a tricky macro.
<<<
I added tobibeer also.
<<<
The best way to prove it's worth resurrecting is to show spaces where you couldn't live without the concertina.
<<<
That's right :) and it is the more difficult part, since the macros, I want to live there, need some tweaking.
Thanks for the space!
-m
----
----
2010.10.01
I liked the concertina, because it was possible to open eg: 5 tiddlers with 6 clicks, and to permanently display the information inside the relavant tiddler.
With the followButton popup you need to click 10 times, to open all tiddlers, which are spread all over the display area. I really don't like this popup there.
I like the concertina idea. But I found the implementation way to complicated.
I like the idea, that there is a info area inside a tilddler, which can be opened and closed. With or without animation. According to global settings.
I like the idea, that the interface explanes itself, for unexperienced useres. (Even if the explanation is scary, and tells you what happens with your revisions, if you click "make this tiddler public". May be it should have been a link to a tiddler, which explanes what is, private and what is public. And how it is implemented.)
I like the idea, that there is a core mechanism which can display tiddler related stuff, that can be prepared outside core functions.
I think about a system, similar to my SvgEvent_xxx system (which seems to be way to complicated too), that triggers an events, and a listener knows what to do.
In this case the concertina is the listener, and knows two functions.
concertina.view content coming from a tiddler
concertina.remove content (remove the DOM element, not the tiddler)
A button, svg element, img, function .... knows how to prepare tiddler related content, that should be displayed.
It writes some stuff to a doNotSave tiddler, and fires a concertina.view(tiddler.title+'_c') event.
The listener opens the hidden tiddler, and the core wikify macro handles the presentation.
This would be as simple, as to include a comments or notes area, but with any element, anywhere on the display.
What would I want to display inside the concertina.
*Metadata
*the deliciusTaggingPlugin,
*the TagSearchPlugin,
*custom fields + FieldsEditorPlugin,
*jon's fields add/edit plugin,
*an editSection plugin
*input forms
*a list of backlinks/references
*a mindMap with this tiddler as the root
*....
May be it was allready there in the tw core, but we didn't see it.
/***
|''Requires''|codemirror.js|
|''License''|[[codemirror.js]]|
***/
//{{{
CodeMirror.runMode=function(e,t,n,r){var i=CodeMirror.getMode(CodeMirror.defaults,t),s=n.nodeType==1,o=r&&r.tabSize||CodeMirror.defaults.tabSize;if(s){var u=n,a=[],f=0;n=function(e,t){if(e=="\n"){a.push("<br>"),f=0;return}var n="";for(var r=0;;){var i=e.indexOf(" ",r);if(i==-1){n+=CodeMirror.htmlEscape(e.slice(r)),f+=e.length-r;break}f+=i-r,n+=CodeMirror.htmlEscape(e.slice(r,i));var s=o-f%o;f+=s;for(var u=0;u<s;++u)n+=" ";r=i+1}t?a.push('<span class="cm-'+CodeMirror.htmlEscape(t)+'">'+n+"</span>"):a.push(n)}}var l=CodeMirror.splitLines(e),c=CodeMirror.startState(i);for(var h=0,p=l.length;h<p;++h){h&&n("\n");var d=new CodeMirror.StringStream(l[h]);while(!d.eol()){var v=i.token(d,c);n(d.current(),v,h,d.start),d.start=d.pos}}s&&(u.innerHTML=a.join(""))};
//}}}
{{{
Name:SimplyGray
Background:rgb(232,232,236)
Foreground:rgb(18,18,22)
PrimaryPale:rgb(255,255,255)
PrimaryLight:rgb(204,205,213)
PrimaryMid:rgb(83,84,101)
PrimaryDark:rgb(63,64,76)
SecondaryPale:rgb(255,255,255)
SecondaryLight:rgb(210,213,204)
SecondaryMid:rgb(95,101,83)
SecondaryDark:rgb(72,76,63)
TertiaryPale:rgb(255,255,255)
TertiaryLight:rgb(213,208,204)
TertiaryMid:rgb(101,92,83)
TertiaryDark:rgb(76,70,63)
Error:#f88
}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke="#4d4d4d" stroke-miterlimit="4" fill="none">
<path id="path3640" stroke-linejoin="round" style="stroke-dasharray:none;" d="m33.165,50.126-10.258,9.3293-2.0113,4.3956,4.2474-2.1224,9.8299-9.5985-1.8075-2.004z" stroke-linecap="butt" stroke-width="1.60000002"/>
<path id="path3642" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m13.981,27.04,12.705,0" transform="matrix(0.8, 0, 0, 0.8, 13, 43)" stroke-linecap="round" stroke-width="2"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<g id="iconSymbol" stroke="#4d4d4d" fill="none" class="showSY">
<path stroke-linejoin="round" d="m31.517,48.69-12.734,12.078,7.0859-1.3033-1.8415,7.4961,13.207-11.835-5.7181-6.4354z" stroke-miterlimit="4" stroke-width="1.60000002"/>
</g>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
! TiddlySpace Numbers
I did some refactoring @cdent posted at the discussion groups, since the numbers are hard to compare.
[[TiddlySpace Numbers for 2013 |http://groups.google.com/group/tiddlyspace/browse_thread/thread/6db1314f8161e105]]
[[Similar info from June 2011|http://groups.google.com/group/tiddlyweb/msg/1228b67bdfb33c01]]
!! The Public Service
| Web |>|>|
| . | 12-2012 | 06-2011 |
|hits / day | ~120,000 | 122,245 |
|hits / unique | ~11,000 | n.a. |
|spiders | ~30% | ~35% |
<<<
//info from cdent 2013. Jan 09 at the dicussion group.//
One thing that looks weird from that is that the number of hits/day has gone down while the number of users has gone up:
2012 2010
hits / day ~120,000 122,245
It's like this not because overall use is down, but because far more of the tiddlers on the server have long term cache headers, meaning that repeat visitors make far fewer requests than they used to while still getting the same stuff.
<<<
| Absolute Numbers |>|>|
| . | 12-2012 | 06-2011 |
|users | ~6,500 | 2,015 |
|spaces | ~10,000 | 3,857 |
|recipes | 19,436 | n.a. |
|bags | 29,979 | n.a. |
|tiddlers | 383,136 | 176,110 |
|revisions | 896,690 | 355,720 |
| New Content |>|>|
| . | 12-2012 | 06-2011 |
|tiddlers created / day | 358 | n.a. |
|tiddlers modified / day | 564 | n.a |
|new users in dec | 146 | n.a. |
|users / year | 2,349 | n.a. |
|spaces / year | 3,114 | n.a. |
| Tech |>|>|
| . | 12-2012 | 06-2011 |
|database size | 4.6 GB | 1 GB |
|queries / sec | 24 | 27.5 |
|read | 97% | 94% |
|write | 3% | 6% |
|queries / sec cache | 316 | 303 |
|hit to miss ratio, cach (5 days) | 122:1 | n.a. |
|items in cach| 760,000 | n.a |
|cach size | 4GB | 1GB |
!! The Project
* 2702 commits to the core code base since March 2010.
* 10 contributors.
! Twitter Cards - Twitter Developers
in reply to [[Twitter Cards - Twitter Developers|http://bengillies.tiddlyspace.com/Twitter%20Cards%20|%20Twitter%20Developers]] at @bengillies:
>[[Twitter Cards > Twitter Developers|https://dev.twitter.com/docs/cards]]
>What do people think about adding this sort of thing to the HTML repr?
I personally think tweets are noise but now they try to add content.
I didn't have a twitter account until ben pointed to "Twitter cards". I do like the fact, that if a content provider wants to get a good card presentation the sites meta content needs to be summarized / refactored. Twitter will cut the "description" section at 200 chars. So just copy paste or use the first lines from the site, won't result in a good card content.
The purpose I'd want to use a "Twitter Card" is to drive traffic to the TS site. To do this it needs some good "teaser text" and it needs to look good. For me "a picture tells more than 1000 words". So well choosen pictures will enrich the content. Creating a pleasant user experience will be an advantage over "text only".
At the moment, the content you tweet is stored at there place. You can't modify it. If they add metacontent from a space, that you control, to there card, there is the possibility to modify this content. Assumed, that the crawlers visit you more than once. But imo twitter wants to be up to date, so they probably will do so (needs to be checked).
If they don't, you could tell them, that they try to sell yesterdays stories.
!! Positive Side Effects
Creating some well made meta data to a tiddler imo will have some positive side effects for ~TiddlySpace too.
* It could be used to produce a better TS RSS feed. At the moment TS RSS contains the whole tiddler text.
** If a tiddler contains twitter metadata, only this one should be shown.
** If there is no metadata, it should list the "tiddler title only".
* It could be used to get a more interesting @news space.
** At the moment there is no possibility to programmatically produce a pleasant @news overview. The only view that can be produced is an "activity" view.
* It could be used to overcome some SearchShortcomings@pmario as a JSON search result will contain custom fields and hopefully a nice "twitter:description" summary.
* The picture url could be used to create picture nvigation buttons for my @simplicity space.
* The TS realtime view could use the pictures and the description text (hovering the button) too
* There could be a ~TiddlyWeb / ~TiddlySpace lens for unity. Similar to [[Wikipedia lens|http://www.omgubuntu.co.uk/2012/05/wikipedia-unity-lens-adds-snippets-thumbnails-in-latest-update]].
** Creating a card type lens for ~TiddlyWeb at the moment is quite hard, since you'd need to wikify TW syntax. If there is a description field, it would be relatively simple ...
* ... may be some more
!! Implementation Ideas
* It would be easy to create a TW EditTemplate, that has the possibility to add "Twitter Card" content.
* It would be needed, to use custom fields, to store the meta data. eg: "twitter:card, twitter:title, twitter:description ..."
** one ui per card type
* Since twitter understands [[open graph|http://ogp.me/]] specification, this one could be used too. (I personally would prefere a connection to twitter more, than to facebook)
<<activity supress:spaceSiteIcon supress:userSiteIcon >>
! New Icons For neui-em Theme
* @neui-em got new "main icons".
* The new icons contain a title attribute, that displays a tooltip, if you hover them with the mouse. The text is hardcoded into the icon atm.
* The permalink icon has changed: <<image tfgPermaview.svg>>
|linkTable|k
|width:400px; !by modified date |width:400px; !by date created |
|vertical-align:top;padding-left:20px;<<timeline "modified">>|vertical-align:top;padding-left:20px;<<timeline "created">>|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" class="smallOnActive">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<g id="iconSymbol" stroke="#4d4d4d" stroke-linecap="round" stroke-dasharray="none" stroke-miterlimit="4" stroke-width="1.60000002" fill="none" class="showSY">
<path stroke-linejoin="round" d="m21.763,50.448,8.4828-0.000001-5.7033,7.7568,4.2356-1.4238-0.71852,4.4997,5.472-7.3053,0,11.126-11.769,0z"/>
<path stroke-linejoin="miter" d="m30.667,50.506,2.8355,2.9981"/>
</g>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
<<tiddler FollowTemplate>>
!MPTW - ~MonkeyPirateTiddlyWiki
* Learn more at: http://mptw.tiddlyspot.com
-----
MPTW is a great TiddlyWiki modification from Simon Baird, that introduces TagglyTagging. It inspired me to create a 3 part howTo "tweak MPTW"
http://a-pm-part1.tiddlyspot.com/
http://a-pm-part2.tiddlyspot.com/
http://a-pm-part3.tiddlyspot.com/
Tested again 04.01.2012
Doesn't work with latest FF (ubuntu 11.10, win7)
Works with Chrome/ium ..
----
autolink doesn't work with FF.
may be becsause of console.log.
PS: I'll remove this tiddler, if fixed, so don't reference to it.
|~ViewToolbar|+cmEdit cloneTiddler tagSearch newTagged saveDraft closeTiddler > < addNow fields revisions permalink references closeOthers untagOthers tagOthers > pubRev syncing jump publishTiddlerRevision closeTiddler <|
|~EditToolbar|cmSave saveDraft addNow savePublicTiddler -cancelTiddler deleteTiddler|
|~RevisionToolbar|fields revert >|
<<image tfgNewTiddler.svg>><<image tfgNewJournal.svg>><<image tfgSaveToWeb.svg>><<image tfgPermaview.svg>><<image tfgCloseAll.svg>>
/***
|''Name''|LineBreakHack|
|''Description''|formatter modifying TiddlyWiki's handling of line breaks, in front and after headings, lists and quots|
|''Author:''|Pietsch Mario|
|''Version''|0.3.1|
|''Status''|stable|
|''Source''|http://line-break-hack.tiddlyspace.com/#LineBreakHack|
|''Documentation''|http://line-break-hack-info.tiddlyspace.com/#LineBreakHackInfo|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
!!!Description
<<<
This formatter modifies the way line breaks in ~TiddlyWiki markup are rendered;
Linebreaks for headings, list, quotes are changed.
<<<
!!! Revision History
<<<
!!!! V0.3.1 (2012-01-17)
* Removed the "paragraph" lineBreak because it creates quirks with inter TiddlySpace transclusion.
* Two linebreaks now produce two lines again.
!!!!V0.3 (2010-09-29)
*Two linebreaks now produce one empty line.
**Have a look at {{{lineBreak.match}}}
<<<
***/
//{{{
(function(formatters) { //# set up alias
// modify line-break formatter to find more than one \n
// var lineBreak = formatters[formatters.findByField("name", "lineBreak")];
// lineBreak.match = "\\n+|<br ?/?>";
// lineBreak.match = "\\n{1,2}|<br ?/?>";
//remove one line break before heading.
var heading = formatters[formatters.findByField("name", "heading")];
merge( heading, {termRegExp: /(\n+)/mg});
heading.match = "^\n?!{1,6}";
heading.handler = function(w) {
if (w.matchText[0]=='\n') w.matchLength = w.matchLength - 1;
w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength), this.termRegExp);
};
for (var i=0; i<formatters.length; i++) {
if (formatters[i].name == "list") {
merge( formatters[i], {termRegExp: /(\n{1,2})/mg});
}
if (formatters[i].name == "quoteByBlock") {
merge( formatters[i], {termRegExp: /(^<<<(\n{1,2}|$))/mg});
}
if (formatters[i].name == "quoteByLine") {
merge( formatters[i], {termRegExp: /(\n{1,2})/mg});
break;
} // if ..
} // for ..
})(config.formatters); //# end of alias
//}}}
<<tiddler FollowTemplate>>
//{{{
config.shadowTiddlers["StyleSheetNeuiEm"]="/*{{{*/\n"+
".image .showFG {\n"+
" opacity: 0;\n"+
"}\n"+
"\n"+
".image:hover .showFG {\n"+
" opacity: 1;\n"+
"}\n"+
"/*}}}*/";
store.addNotification("StyleSheetNeuiEm",refreshStyles);
//}}}
/***
|''Name:''|TagSearchPlugin|
|''Description:''|Provides a drop down listing current tags and others to be set. Based on [[x-tagger|http://tbgtd.tiddlyspot.com/#x-tagger]] which in turn was once based on [[TaggerPlugin|http://tw.lewcid.org/#TaggerPlugin]].|
|''Author:''|[[Tobias Beer]]|
|''Version:''|1.2.0 (2010-10-10)|
|''Documentation:''|http://tagsearch.tiddlyspot.com|
|''Source:''|http://tagsearch.tiddlyspot.com/#TagSearchPlugin|
|''~TiddlyWiki:''|Version 2.5 or better|
/%***/
(function(e){config.macros.tagsearch={cfg:{defaultSource:"",defaultMore:"",defaultMode:1,keepModified:false,sidebarOffset:20,newAtSingle:30,newAt:18,excludeTagged:"",toolbar:"",label:"tags",options:"Options",more:"More...",tooltip:"Manage tiddler tags",notags:"no tags set...",aretags:"Current tags",addTag:"Add tag...",addTags:"Set tag...",txtEdit:"~ edit categories...",txtEditTip:"edit tiddler with GTD tag categories used by x-tagger",txtNew:"~ add another tag",txtRemove:"remove tag %0",txtAdd:"set tag %0",txtFor:"To be tagged... ",txtCtrl:" (hold SHIFT to just add it or CTRL to replace in category)",promptNew:"Enter new tag:",modeAsk:"Do you want to remove existing tags from category '%0'?\nCancel simply adds tag '%1'."},handler:function(k,g,i,l,h,n){var m=this.cfg,j=story.findContainingTiddler(k),f=h.parseParams("tagman",null,true);e(createTiddlyButton(k,getParam(f,"label",m.label),getParam(f,"tooltip",m.tooltip),this.click,"button")).attr({id:this.newId("btntgs"),tid:(j?j.getAttribute("tiddler"):"")}).data({pa:i,p:f})},click:function(O){var k,G,S,R,K=[],w=true,W,V,U,M,A,Y,T,D,N,L,J=[],C,f,H,aa=O||window.event,X=e(this),F=X.attr("popup"),B=window.event?"keydown":"keypress",I=config.macros.tagsearch,ab=I.cfg,u=X.data("pa"),Q=X.data("p"),h=u.contains("toolbar"),v=getParam(Q,"source",ab.defaultSource),q=getParam(Q,"more",ab.defaultMore),Z=!u.contains("nosearch"),z=!u.contains("notags"),E=!u.contains("nomore"),n=getParam(Q,"goto",""),o=parseInt(getParam(Q,"mode")),g=getParam(Q,"tiddler",""),r=g?g:X.attr("tid"),ac=(getParam(Q,"exclude","")+" "+ab.excludeTagged).readBracketedList(),y=nu=v?ab.newAt:ab.newAtSingle,P=store.getTiddler(r);if(!r){return}o=isNaN(o)?ab.defaultMode:o;ac.map(function(i){K.pushUnique(i)});for(W=0;W<ac.length;W++){store.getTaggedTiddlers(ac[W]).map(function(i){K.pushUnique(i.title)})}if(v&&!store.getTiddlerText(v)){return false}if(F){D=e("#"+F)[0];e(D).empty()}if(!D){M=true;F=I.newId("tgspop");D=Popup.create(this);e(D).addClass("tgs").attr({id:F}).data({btn:X,tiddler:r,source:v,mode:o}).click(I.noBubble);X.attr("popup",F)}if(v){C=store.getTiddlerText(v).readBracketedList();for(L=0;L<C.length;L++){if(!K.contains(C[L])){H=store.getTaggedTiddlers(C[L]);J.push("TAG:"+C[L]);for(N=0;N<H.length;N++){if(!K.contains(H[N].title)){J.push(H[N].title)}}}}}else{J=store.getTags()}G=P?P.tags.sort():[];Y=function(j,i){return createTiddlyElement(createTiddlyElement(j,"li",null,null),"ol",null,i?i:null)};A=function(j,x,i,p){var m,l;m=createTiddlyElement(createTiddlyElement(j,"li"),"span",null,null);l=e(createTiddlyButton(m,x,p.format(["'"+i+"'"]),I.setTag,"button toggleButton",null));l.data({tiddler:r,tag:i,source:v,mode:o});insertSpacer(m);createTagButton(m,i)};S=Y(D,"tgside");if(config.macros.gotoTiddler&&Z){R=Y(S);if(g){U=createTiddlyElement(R,"li",null,"addto","");wikify("{{title{"+ab.txtFor+"}}}<<tag [["+r+"]]>>",U);R=Y(S)}createTiddlyElement(R,"li",null,"title",ab.addTag);wikify("<<gotoTiddler "+n+" >>",R);e("input",D).bind(B,I.noBubble).data("notify",config.macros.tagsearch.notify).focus()}R=Y(S);createTiddlyElement(R,"li",null,"title",ab.aretags);if(G.length==0){wikify("{{notags{"+ab.notags+"}}}",R)}else{for(L=0;L<G.length;L++){A(R,"[X]",G[L],ab.txtRemove)}}if(z){for(W=0;W<J.length;W++){nu++;f=v?J[W]:J[W][0];if(f.indexOf("TAG:")==0){f=f.substr(4);if(nu>y){nu=0;S=Y(D)}R=Y(S);nu++;createTiddlyLink(createTiddlyElement(R,"li",null,null),f,f,"title")}else{if(!G.contains(f)&&!K.contains(f)){if(!v&&nu>y||v&&nu>ab.newAtSingle){nu=0;S=Y(D);R=Y(S);if(w){createTiddlyElement(createTiddlyElement(R,"li",null,null),"li",null,"title",ab.addTags);w=false}}A(R,"["+String.fromCharCode(160,160,160)+"]",f,ab.txtAdd+(v?ab.txtCtrl:""))}}}}if(E){S=Y(D,"tgside");R=Y(S);createTiddlyElement(R,"li",null,"title",ab.options,null);createTiddlyButton(createTiddlyElement(R,"li"),ab.txtNew,null,I.setTag,"tsopt",null,null,{tiddler:r});if(v){createTiddlyButton(createTiddlyElement(R,"li"),ab.txtEdit,ab.txtEditTip,onClickTiddlerLink,"tsopt",null,null,{tiddlyLink:v.split("##")[0]})}w=true;if(q){T=store.getTiddlerText(q).readBracketedList();if(T.length>0){for(W=0;W<T.length;W++){f=T[W];if(f.indexOf("TAG:")==0){f=f.substr(4,f.length-4);R=Y(S);createTiddlyLink(createTiddlyElement(R,"li",null,null),f,f,"title");k=store.getTaggedTiddlers(f);for(V=0;V<k.length;V++){f=k[V].title;if(!G.contains(f)&&!K.contains(f)){A(R,"["+String.fromCharCode(160,160)+"]",f,ab.txtAdd)}}}else{if(w){R=Y(S);createTiddlyElement(R,"li",null,"title",ab.more);w=false}if(!G.contains(f)&&!K.contains(f)){A(R,"["+String.fromCharCode(160,160)+"]",f,ab.txtAdd)}}}}}}if(M){Popup.show(D,false);if(h){N=document.getElementById("sidebar");D.style.left="";D.style.right=(ab.sidebarOffset+(N?N.offsetWidth:0))+"px"}}return I.noBubble(aa)},setTag:function(w){var q,j,z,l=true,n,u,s,g,v=w||window.event,k=config.macros.tagsearch,y=k.cfg,f=e(this),o=f.closest(".tgs"),i=o.data("btn"),A=f.data("tag"),B=o.data("tiddler"),h=o.data("source"),r=parseInt(o.data("mode"));if(!A){z=prompt(y.promptNew,"");if(!z){return false}else{A=z}}tid=k.exists(B,A);if(tid){u=tid.tags;if(!u.contains(A)){if(h&&r<2&&!v.shiftKey){j=store.getTiddlerText(h).readBracketedList();findTagged:for(q=0;q<j.length;q++){g=j[q];s=store.getTaggedTiddlers(g).map(function(m){return m.title});if(s.contains(A)){s.splice(s.indexOf(A),1);if(!v.ctrlKey&&r==1&&u.containsAny(s)){l=confirm(y.modeAsk.format([g,A]))}if(l){for(n=0;n<s.length;n++){g=s[n];if(u.contains(g)){store.setTiddlerTag(B,false,g)}}}break findTagged}}}store.setTiddlerTag(B,true,A)}else{if(!z){store.setTiddlerTag(B,false,A)}}n=store.getTiddler(B);store.saveTiddler(B,B,n.text,y.keepModified?n.modifier:config.options.txtUserName,y.keepModified?n.modified:new Date(),n.tags,n.fields)}if(config.options.chkAutoSave){autoSaveChanges()}i.click();o.find("input").focus();return k.noBubble(v)},newId:function(f){return f+Math.random().toString().substr(3)},notify:function(f,h){var j=e(h).closest(".tgs"),g=e("form input",j)[0];t=config.macros.tagsearch.exists(j.data("tiddler"),f);if(t&&!t.tags.contains(f)){store.setTiddlerTag(t.title,t,f)}j.data("btn").click();g.select()},exists:function(i,g){if(!store.getTiddler(i)){var h=merge({},config.defaultCustomFields);store.saveTiddler(i,i,"",config.options.txtUserName,new Date(),g,h);return false}return store.getTiddler(i)},noBubble:function(g){var h=g||window.event,f=resolveTarget(h);if(h.keyCode==27){Popup.remove(0)}else{if(h.type!="click"&&f.nodeName.toUpperCase()=="INPUT"){return true}}if(e(f).hasClass("tiddlyLink")){return true}Popup.remove(1);h.cancelBubble=true;try{event.keyCode=0}catch(h){}if(window.event){h.returnValue=false}if(h.preventDefault){h.preventDefault()}if(h.stopPropagation){h.stopPropagation()}return false}};config.commands.tagSearch={};var d=config.macros.toolbar;d.createCommandTAGS=d.createCommand;d.createCommand=function(f,h,g,i){if(h=="tagSearch"){wikify("<<tagsearch toolbar "+config.macros.tagsearch.cfg.toolbar+">>",f);e(f.lastChild).attr({commandName:"tagSearch",tiddler:g.title})}else{d.createCommandTAGS.apply(this,arguments)}};var b=config.macros.gotoTiddler;if(b){b.processItem=function(i,g,h,f){if(!i.length){return}h.style.display=f?"block":"none";if(i=="*"){story.search(g.value);return false}if(!f){g.value=i}var j=e(g).data("notify");if(j){j.call(this,i,g)}else{story.displayTiddler(null,i)}return false};b.IEtableFixup="%0"}var c=store.getTiddlerText("ColorPalette::TertiaryMid"),a=store.getTiddlerText("ColorPalette::TertiaryDark");config.shadowTiddlers.StyleSheetTagSearch="/*{{{*/\n.tgs {padding:7px !important;-moz-border-radius:5px; -webkit-border-radius:5px;border-radius:5px;}\n.tgs li a, .tgs .quickopentag .tiddlyLink {display:inline;padding:2px;clear:none;}\n.tgs li a.toggleButton {display:inline;margin-left:5px;}\n.tgs .title {margin:3px 0 0 5px;font-weight:bold;font-size:150%;color:"+c+";padding:0;}\n.tgs form{display:block;float:left;clear:both;padding-left:5px !important;}\n.tgs .addto .quickopentag{display:block;clear:both;padding:5px;font-size:120%;}\n.tgs .notags, .tsopt{display:block;clear:both;margin:5px;}\n.tgs .highlight{background:"+a+";}\n.tgs ol{margin:0;padding:0 0 5px 0;}\n.tgs li{display:block;float:left;padding-bottom:10px !important;}\n.tgs li span{line-height:1em;}\n.tgs li ol li{clear:both;min-width:120px;display:inline;border:1px solid transparent;}\n.tgs li ol li:hover{border:1px solid "+c+";}\n.tgs li ol li ol li{padding:0 !important;}\n.tgs li ol li ol li:hover{border:1px solid transparent;}\n.tgside li ol li {min-width:150px;}.tgs .quickopentag {display:inline;}\n.tgs .quickopentag .tiddlyLink:hover {text-decoration:underline;}\n.tgs .quickopentag .button {border:0;padding:2px;font-size:1.5em;}\n/*}}}*/";store.addNotification("StyleSheetTagSearch",refreshStyles)})(jQuery);
//%/
<<tiddler TEMPLATES##follow>>
|''Name:''|[[NeUIemTheme]]|
|''Description:''|Your description here!|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspace.com]]|
|''Gen.Description:''|Automatically generated from: tsNeUIemProject|
|''PageTemplate:''|##PageTemplate|
|''ViewTemplate:''|##ViewTemplate|
|''EditTemplate:''|##EditTemplate|
|''RevisionTemplate:''|NeUIemTheme##RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
|''UsedClones:''|StyleSheetHeaderMp StyleSheetMenuBarMp StyleSheetSideBarMp StyleSheetTiddlerMp StyleSheetTiddlySpaceMp StyleSheet_neui-em EmasticSystem NeuiemZzConfig:zzConfig TerminateStyleSheet:StyleSheet CSideBarTabs CSidebarOptions CSidebarTools NeuiemSidebarTools:SidebarTools TopMenu SideBarOptions OptionsPanel [[sidebarSearch]] FontPalette ToolbarCommands GettingStarted NeUIemTheme01 NeUIemTheme02 NeUIemTheme03 NeUIemTheme04 |
!Important
If any of the obove clones is missing, the theme may not work.
!PageTemplate
<!--{{{-->
<!-- tsRowTitle -->
<div class='dp100 header clearfix'>
<!-- tsColTitle -->
<div class='dp80'>
<!-- BoxTsHeader -->
<div class='box headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<!-- tsColSearch -->
<div class='dp20'>
<!-- tsBoxGoto -->
<div id='sidebarSearch' class='box searchForeground'>
<div refresh='content' tiddler='sidebarSearch'></div>
</div>
</div>
<!-- tsRowMenuBar -->
<div id='menuBar' class='dp100 clearfix'>
<!-- tsColTopMenue -->
<div class='dp60'>
<!-- tsBoxTopMenue -->
<!-- horizontal TopMenu -->
<div class='box topMenu clearfix' refresh='content' tiddler='TopMenu'></div>
</div>
<!-- tsColThemeSwitcher -->
<div class='dp40'>
<!-- tsBoxThemeSwitcher -->
<div id='sidebarOptions' class='dpfr' refresh='content' tiddler='SideBarOptions'></div>
</div>
</div> <!-- row -->
</div> <!-- row -->
<!-- tsRowBody -->
<div class='dp100 clearfix row'>
<!-- tsColSidebar -->
<div id='sidebar' class='dp15 dpfr' style='width:15%; position:relative;'>
<!-- tsBoxSidebarTools -->
<div id='sidebarTools' class='box' refresh='content' force='true' tiddler='CSidebarTools'></div>
<!-- tsBoxSidebarTabs -->
<div id='sidebarTabs' class='box' refresh='content' force='true' tiddler='CSideBarTabs'></div>
</div>
<!-- tsColMainMenu -->
<div class='dp15'>
<!-- tsBoxMainMenu -->
<!-- original MainMenu menu -->
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
</div>
<!-- tsColDisplayArea -->
<div id='displayArea' class='dp70'>
<!-- tsBoxMessageArea -->
<div id='messageArea' class='box'></div>
<!-- tsBoxBreadCrumbs -->
<div id='breadCrumbs' class='breadCrumbs box'></div>
<!-- tsBoxTiddlersBar -->
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<!-- tsBoxTiddlerDisplay -->
<div id='tiddlerDisplay' class='box'></div>
</div>
</div> <!-- row -->
<!--}}}-->
!ViewTemplate
<!--{{{-->
<!-- tsVT_NEUIem -->
<div class='dp100 clearfix'>
<!-- tsVT_toolbar -->
<div class='dp100'>
<!-- tsBoxVT_FollowPlaceHolder -->
<!--div class='followPlaceHolder' macro='followTiddlersButton'-->
<div class='followPlaceHolder' macro='linkedTiddlers'>
<span macro="view title replyLink"></span>
</div>
<!-- tsBoxVT_Toolbar -->
<div class='box toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]] icons:yes'></div>
</div>
<!-- tsVT_leftCol -->
<div class='dp10'>
<!-- tsBoxVT_SiteIcon -->
<div class='box spaceSiteIcon' macro='tiddlerOrigin label:yes height:48 width:48'></div>
<!-- BoxVT_Calender -->
<div class='box calendar' macro='viewRevisions page:5'>
<div class='month' macro='view modified date mmm'></div>
<div class='date' macro='view modified date 0DD'></div>
<div class='time' macro='view modified date 0hh:0mm'></div>
<br />
<div class='month' macro='view created date mmm'></div><div class='date' macro='view created date 0DD'></div>
<!-- div class='time' macro='view created date 0hh:0mm'></div -->
</div>
<!-- BoxVTts_tagged -->
<div class='box tagged' macro='tags'></div>
<div class='box' macro='tiddler CTagBox'></div>
</div>
<!-- tsViewTemplate -->
<div class='dp90'>
<!-- tsBox_ModifierIcon -->
<div class='box modifierIcon dpfr'
macro='view modifier SiteIcon label:yes height:30 width:30 labelPrefix:"m: "'>
</div>
<!-- tsBoxVT_Title -->
<div class='titleContainer'>
<div class='box title' macro='view title'></div>
</div>
<!-- tsBox_concertina -->
<div class='box concertina clear'></div>
<div class='cmBuffer' refresh='content' tiddler='cmB1'></div>
<!-- tsBoxVT_Body -->
<div class='box content'>
<div class='viewer' macro='view text wikified'></div>
<div class='viewer' macro='showWhenTagged topic'>
<h3>Others say</h3>
<div macro='tsScan {{tiddler.title}} fat:1 template:"TEMPLATES##scanComment" query:"select=modifier:!pmario" '></div>
</div>
</div>
<!-- tsBoxVT_TagglyTaggingFooter -->
<div class="clear box tagglyTagging" macro="tagglyTagging"></div>
<!-- tsBox_StoryGlue -->
<div class='box storyGlue' macro='storyGlue fsStory ACTIVESTORY'></div>
</div>
</div> <!-- row -->
<!--}}}-->
!EditTemplate
<!--{{{-->
<!-- tsET_NEUIem -->
<div class='dp100 clearfix'>
<!-- tsEditTemplate -->
<div class='dp100'>
<!-- BoxET_tsEditToolbar -->
<div class='box dpfr toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]] icons:yes'></div>
<!-- BoxET_tsSetPrivate -->
<div class="box dpfr privacyEdit" macro='setPrivacy label:no interactive:yes'></div>
<div class='box dpfr editSpaceSiteIcon' macro='tiddlerOrigin height:25 width:25 label:no interactive:no'></div>
<!-- BoxET_tsTitle -->
<div class='box title' macro='view title'></div>
<!-- BoxET_tsEditTitle -->
<div class='box editor' macro='edit title'></div>
<div class='toolbar' macro='typeChooser'></div>
<div macro='annotations'></div>
<!-- BoxET_tsEditBody -->
<div class='box editor' macro='edit text'></div>
<!-- BoxET_tsTagging -->
<div class='box save editor' macro='edit tags'></div>
<!-- BoxET_tsEditFooter -->
<div class='box editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
</div>
</div> <!-- row -->
<!--}}}-->
!RevisionTemplate
<!--{{{-->
<!-- tsRT_NEUIem -->
<div macro='slideRevision'></div>
<div class='dp100 clearfix'>
<!-- tsRT_toolbar -->
<div class='dp100'>
<!-- tsBoxVT_FollowPlaceHolder -->
<div class='followPlaceHolder' macro='followTiddlers'>
<span macro="view title replyLink"></span>
</div>
<!-- tsBoxRT_Toolbar -->
<div class='box toolbar' macro='toolbar [[ToolbarCommands::RevisionToolbar]] icons:yes'></div>
</div>
<!-- tsVT_leftCol -->
<div class='dp10'>
<!-- tsBoxVT_SiteIcon -->
<div class='box spaceSiteIcon' macro='tiddlerOrigin label:yes height:48 width:48'></div>
<!-- BoxVT_Calender -->
<div class='box calendar' macro='viewRevisions page:5'>
<div class='month' macro='view modified date mmm'></div>
<div class='date' macro='view modified date 0DD'></div>
<!-- div class='time' macro='view modified date 0hh:0mm'></div -->
</div>
<!-- BoxVTts_tagged -->
<div class='box tagged' macro='tags'></div>
<div class='box' macro='tiddler CTagBox'></div>
</div>
<!-- tsViewTemplate -->
<div class='dp90'>
<!-- tsBox_ModifierIcon -->
<div class='box modifierIcon dpfr'
macro='view modifier SiteIcon label:yes height:48 width:48 labelPrefix:"modified by "'>
</div>
<!-- tsBoxVT_Title -->
<div class='titleContainer'>
<div class='box title' macro='view title'></div>
</div>
<!-- tsBox_concertina -->
<div class='box concertina clear'></div>
<!-- tsBoxVT_Body -->
<div class='box content'>
<div class='viewer' macro='view text wikified'></div>
</div>
<!-- tsBoxVT_TagglyTaggingFooter -->
<div class="box tagglyTagging" macro="tagglyTagging"></div>
<!-- tsBox_StoryGlue -->
<div class='box storyGlue' macro='storyGlue fsStory ACTIVESTORY'></div>
</div>
</div> <!-- row -->
<!--}}}-->
!StyleSheet
/*{{{*/
Version: 1.0 - 2010.08.12
/*****************************************************/
/*-- some simple rules to change the global layout --*/
/*-- margin should not be uses for row, col, box --*/
/*-- margin is used to adjust special elements --*/
/*-- The layout doesn't allow padding-left/right or margin-left/right ! for rows and cols --*/
.row {
margin: 0;
padding: 0;
margin-top: 0.5em;
}
/*-- The layout doesn't allow padding-left/right or margin-left/right ! for rows and cols --*/
/*-- col is not assigned to layout yet --*/
.col {
margin: 0;
padding: 0;
}
/*-- if you want more space between 2 columns use box 2nd and 4th parameter. --*/
/*-- boxes must have padding-bottom: 0; !! --*/
.box {
margin: 0;
padding: 0.5em 0.5em 0 0.5em;
}
/* general stuff */
.noBullets ul {
list-style:none;
}
.noNumbers ol {
list-style:none;
}
.noBr br {
display: none;
}
/* prefer monospace for editing */
.editor textarea, .editor input {
font-size: 90%;
font-family: [[FontPalette::twEditor]], 'Courier New', monospace;
background-color:[[ColorPalette::TertiaryPale]];
}
/*-- emastic System --*/
[[EmasticSystem]]
/*-- theme specific stuff --*/
[[StyleSheet_neui-em]]
/*-- call the standard StyleSheet --*/
[[StyleSheet]]
/*}}}*/
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#CC9900" offset="0"/>
<stop id="stop2" stop-color="#E8D18B" offset="0.66462"/>
<stop id="stop3" stop-color="#CC9900" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" transform="matrix(0.979566, -0.500632, 0.735105, 0.667118, -41.7482, 33.1452)" stroke="#4d4d4d" stroke-linecap="butt" stroke-width="0.80000001px" fill="none">
<path id="path3696" d="m37.954,54.163-4.5532,5.7819-0.03139-4.2335-7.7522,0,0-2.605,7.7522,0,0-3.4444,4.5846,4.501z"/>
<path id="path3719" d="m17.41,60.825,4.4254-5.6117,0.03139,4.2335,7.7522,0,0,2.605-7.7522,0,0,3.4444-4.4568-4.6712z"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
http://westcoastlogic.com/lawnchair/
!Copyright (c) $1
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
Neither the name of the Author nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
@@Please do not modify this tiddler; it was created automatically upon space creation.@@
!Attention
If you want to use it. Only copy from source. Because otherwise, the content will be rendered recursively.
{{{
!scan
<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>> @$1 says
<<<
<<view text wikified>>
<<<
!end
}}}
{{{
!scanComment
<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>> ''@$1 says''
<<<
<<view text wikified>>
<<<
!end
}}}
{{{
!scanTable
|<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>>|@$1 says|
<<<
<<view text wikified>>
<<<
!end
}}}
{{{
!follow
{{dp50{Following: <<following {{tiddler.title}}>> }}}{{dp50{Followers: <<followers {{tiddler.title}}>> }}}
!end
}}}
{{{
!contact
|<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>>|@$1 wants to contact me|
<<view text text>>
!end>
}}}
{{{
!list
<<image http://$1.tiddlyspace.com/bags/$1_public/tiddlers/SiteIcon 24 24>> @$1
<<<
<<view text text>>
<<<
!end
}}}
Click the "new tiddler" button towards the top right of the screen to write something in your space. You'll need to give it a title, some content and, optionally, some tags that will help you identify it later.
!Stuck for ideas?
Not sure what to write about? Not sure what to keep in your space? Other people use ~TiddlySpace for almost anything. How about some of the following:
* [[Save interesting sites|http://bookmarks.tiddlyspace.com]], images or articles from around the web so that you can refer back to them.
* [[Record your family tree|http://familytree.tiddlyspace.com]], store notes on long lost relatives or ancestors and map their relationship to you.
* [[Make up a pocketbook|http://pocketbook.tiddlyspace.com]] to store some useful information in, then print it out, [[fold it up|http://www.pocketmod.com/]], and take it with you.
* [[Plan your holiday|http://the-web-is-your-oyster.tiddlyspace.com/]], record where you're planning to go, note down places of interest and refer back to it later.
* [[Create a mindmap|http://mindmaps.tiddlyspace.com/]] to visualise your inner thoughts and see how they relate to each other.
* [[Set up a questionnaire|http://questionnaire.tiddlyspace.com/]] and get all your friends to answer it.
If you don't like any of those ideas, you can still use this space directly to keep notes and link them together, make a todo list and keep track of everything you're doing, or any one of a hundred million other things.
Still stuck? Check out the @featured space for more suggestions.
You can also [[socialise with others|How to socialise]].
2011.03.11 ben writes
<<<
I suppose the point of rendering the HTML instead of simply showing it is that HTML isn't really that readable, so rendering it, even if not functional, at least means you can read the text. I suppose the main question is which approach is better: rendering the HTML, with its increased bloat, simply showing it as is in text format (with decreased readability) or, I suppose, not showing anything there instead.
<<<
You are right, script stripped html has limited functionality. You can read it. May be, if the "first/small" Plugin can be part of the core. If the sanitizer is detected, it could use it. eg: a seperate space which is default included, but can be excluded. So everyone will be happy.
----
2011.03.10
The first version of the TiddlySpaceDynamicImportTiddlerSanitiser plugin was nice. Quite small and adds some more security to anyway trusted spaces. Now the second version adds a 40kByte html renderer to my space, to get the html code rendered, and the scripts stripped, --which makes the html useless anyway.--
Can I get a link to the first version. I'd like to use the first version. The TS core is way to bloated allready. I don't think it needs another 40k to get the job done.
----
[[Sanitising tiddlers pulled in with the following mechanism]]@bengillies looks good.
<<<
*Any inline CSS is simply ignored
*Any HTML fragments are escaped and stuffed into a <pre> tag
<<<
Since I don't use inline CSS, I don't care, if it is stripped. Real CSS should be preferred anyway.
I'd like to have info with the {{{<pre> block}}}
<!--{{{-->
<pre class='sanitized' title='This <html> block has been converted into comment, to do no harm!'>...</pre>
<!--}}}-->
The {{{title=}}} attribute should give some more info, what happened. See [[here|http://pmario.tiddlyspace.com/#[[Sanitising%20tiddlers%20pulled%20in%20with%20the%20following%20mechanism]%5d]], why it may be important.
The additional {{{class}}} adds the possibility to add some CSS to make it obvious.
/*{{{*/
.sanitized {
border: 1px dotted blue;
}
/*}}}*/
----
testHTMLsanitize@pmbm test it:
{{{
<<tsScan testHTMLsanitize fat:y template:"TEMPLATES##scanComment" query:"select=modifier:pmario">>
}}}
<<tsScan testHTMLsanitize fat:y template:"TEMPLATES##scanComment" query:"select=modifier:pmario">>
<<tiddler FollowTemplate>>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onclick="if(jQuery) jQuery(document).trigger('cCloseAll', {elem:this, comp:{menue:1}})" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})" title="Close all tiddlers (except any, that are being edited)">
<metadata id="metadata14">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<dc:rights>
<cc:Agent>
<dc:title>http://creativecommons.org/licenses/by-nc-sa/3.0/at/</dc:title>
</cc:Agent>
</dc:rights>
<dc:source>http://iconbuilder.tiddlyspace.com</dc:source>
<dc:creator>
<cc:Agent>
<dc:title>Mario Pietsch</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs_bBgTrans">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#FF4646" offset="0"/>
<stop id="stop2" stop-color="#ffcccc" offset="0.66462"/>
<stop id="stop3" stop-color="#FF4646" offset="1"/>
</linearGradient></defs>
<g id="icon">
<rect id="iconBG" stroke="#696969" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" fill="none" class="showBG"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0,-1,1,0,0,0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showFG"/>
<g id="iconSymbol" stroke="#4d4d4d" stroke-linecap="round" stroke-width="1.60000002" class="showSY">
<g>
<path d="m21.166,64.294,4.9545-4.9546"/>
<path d="M26.12,64.294,21.165,59.339"/>
</g>
<g transform="translate(8.3261246,-8.609083)">
<path d="m21.166,64.294,4.9545-4.9546"/>
<path d="M26.12,64.294,21.165,59.339"/>
</g>
<g transform="translate(8.3261246,0)">
<path d="m21.166,64.294,4.9545-4.9546"/>
<path d="M26.12,64.294,21.165,59.339"/>
</g>
<g transform="translate(0.02508651,-8.6271626)">
<path d="m21.166,64.294,4.9545-4.9546"/>
<path d="M26.12,64.294,21.165,59.339"/>
</g>
</g>
<rect id="overlay" stroke="#696969" opacity="0" ry="4.1663" transform="matrix(0,-1,1,0,0,0)" height="25" width="25" y="15.167" x="-70.116" stroke-width="1.2" class="showOV"/>
</g>
</svg>
/***
|''Name''|TiddlySpaceViewTypes|
|''Version''|0.6.0|
|''Status''|@@beta@@|
|''Description''|Provides TiddlySpace specific view types|
|''Author''|Jon Robson|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceViewTypes.js|
|''Requires''|TiddlySpaceConfig TiddlySpaceTiddlerIconsPlugin|
!Usage
Provides replyLink, spaceLink and SiteIcon view types.
!!SiteIcon view parameters
* labelPrefix / labelSuffix : prefix or suffix the label with additional text. eg. labelPrefix:'modified by '
* spaceLink: if set to "yes" will make any avatars link to the corresponding space. {{{<<originMacro spaceLink:yes>>}}}
!Code
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace;
var originMacro = config.macros.tiddlerOrigin;
var tweb = config.extensions.tiddlyweb;
config.macros.view.replyLink = {
locale: {
label: "Reply to this tiddler"
}
};
var _replyButtons = [];
var _replyInitialised, _replyScriptLoaded;
config.macros.view.views.replyLink = function(value, place, params, wikifier,
paramString, tiddler) {
var valueField = params[0];
var imported;
if(valueField == "title") { // special casing for imported tiddlers
var localTitle = tiddler.title;
var serverTitle = tiddler.fields["server.title"];
if(serverTitle && localTitle != serverTitle) {
value = serverTitle ? serverTitle : localTitle;
imported = true;
}
} else {
title = tiddler[valueField] ? tiddler[valueField] : tiddler.fields[valueField];
}
var args = paramString.parseParams("anon")[0];
var label = (args.label) ? args.label : config.macros.view.replyLink.locale.label;
var space;
if(tiddler) {
var bag = tiddler.fields["server.bag"];
space = tiddlyspace.resolveSpaceName(bag);
}
var container = $('<span class="replyLink" />').appendTo(place)[0];
tweb.getUserInfo(function(user) {
if ((!user.anon) && ((space && user.name != space &&
user.name != tiddlyspace.currentSpace.name) || imported)) {
var link = $("<a />")
.text(config.macros.view.replyLink.locale.label)
.appendTo(container)[0];
if(typeof(createReplyButton) === "undefined") {
_replyButtons.push(link);
}
if(_replyInitialised) {
createReplyButton(link);
} else if(!_replyScriptLoaded) {
_replyScriptLoaded = true;
$.getScript("/bags/common/tiddlers/_reply-button.js",
function() {
_replyInitialised = true;
for(var i = 0; i < _replyButtons.length; i++) {
createReplyButton(_replyButtons[i]);
}
_replyButtons = [];
});
}
}
});
};
config.macros.view.views.spaceLink = function(value, place, params, wikifier,
paramString, tiddler) {
var spaceName = tiddlyspace.resolveSpaceName(value);
var isBag = params[0] == "server.bag" && value === spaceName ? true : false;
var args = paramString.parseParams("anon")[0];
var titleField = args.anon[2];
var labelField = args.labelField ? args.labelField[0] : false;
var label;
if(labelField) {
label = tiddler[labelField] ? tiddler[labelField] : tiddler.fields[labelField];
} else {
label = args.label ? args.label[0] : false;
}
var title = tiddler[titleField] ? tiddler[titleField] : tiddler.fields[titleField];
var link = createSpaceLink(place, spaceName, title, label, isBag);
if(args.external && args.external[0] == "no") {
$(link).click(function(ev) {
var el = $(ev.target);
var title = el.attr("tiddler");
var bag = el.attr("bag");
var space = el.attr("tiddlyspace");
bag = space ? space + "_public" : bag;
if(title && bag) {
ev.preventDefault();
tiddlyspace.displayServerTiddler(el[0], title,
"bags/" + bag);
}
return false;
});
}
};
config.macros.view.views.SiteIcon = function(value, place, params, wikifier,
paramString, tiddler) {
var options = originMacro.getOptions(paramString);
if(!tiddler || value == "None") { // some core tiddlers lack modifier
value = false;
}
var field = params[0];
if(field == "server.bag") {
options.notSpace = !originMacro._isSpace(value);
}
tiddlyspace.renderAvatar(place, value, options);
};
})(jQuery);
//}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#FF4646" offset="0"/>
<stop id="stop2" stop-color="#ffcccc" offset="0.66462"/>
<stop id="stop3" stop-color="#FF4646" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" style="stroke-dasharray:none;" transform="matrix(0.579556, -0.579556, 0.579556, 0.579556, -4.21894, 26.7647)" stroke="#4d4d4d" stroke-width="3.19999981" fill="#4d4d4d">
<path id="path3219" style="stroke-dasharray:none;" d="M-7.3399,53.9h16.353"/>
<path id="path3221" style="stroke-dasharray:none;" d="M0.8368,62.077v-16.354"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
Jeremy says:
<<<
I think that pen.io is better compared with a vertical edition of TiddlyWiki, rather than TiddlyWiki itself. It would be interesting to try to clone pen.io with TiddlySpace.
<<<
I tried to reach pen.io's simplicity with [[simplicity|http://simplicity.tiddlyspace.com]] the TiddlySpace. Now I think I've totally failed. Feedback would be welcome.
/***
|''Name''|ToggleTiddlerPrivacyPlugin|
|''Version''|0.7.1|
|''Status''|@@beta@@|
|''Description''|Allows you to set the privacy of new tiddlers and external tiddlers within an EditTemplate, and allows you to set a default privacy setting|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/ToggleTiddlerPrivacyPlugin.js|
!Notes
When used in conjunction with TiddlySpaceTiddlerIconsPlugin changing the privacy setting will also interact with any privacy icons.
Currently use of
{{{<<setPrivacy defaultValue:public>>}}} is in conflict with {{{<<newTiddler fields:"server.workspace:x_private">>}}}
There is an option, found in the tweak tab of the backstage, called txtPrivacyMode. Set this to either ''public'' or ''private'' depending on your security preference. If you choose not to set it then it will default to ''public''.
!Params
defaultValue:[private|public]
Allows you to set the default privacy value (Default is private)
!Code
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace,
macro;
macro = config.macros.setPrivacy = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
if(readOnly) {
return;
}
var el = $(story.findContainingTiddler(place)),
args = paramString.parseParams("name",
null, true, false, true)[0],
container = $("<div />").
addClass("privacySettings").
appendTo(place)[0],
currentSpace = tiddlyspace.currentSpace.name,
currentBag = tiddler ? tiddler.fields["server.bag"] : false,
// XXX: is the following reliable?
isNewTiddler = el.hasClass("missing") || !currentBag,
tiddlerStatus = tiddlyspace.getTiddlerStatusType(tiddler),
customFields = el.attr("tiddlyfields"),
defaultValue = "public",
options = config.macros.tiddlerOrigin ?
config.macros.tiddlerOrigin.getOptions(paramString) :
{};
customFields = customFields ? customFields.decodeHashMap() : {};
if(isNewTiddler || !["public", "private", "unsyncedPrivate",
"unsyncedPublic"].contains(tiddlerStatus)) {
if(args.defaultValue) {
defaultValue = args.defaultValue[0].toLowerCase();
} else {
defaultValue = config.options.chkPrivateMode ?
"private" : "public";
}
defaultValue = defaultValue ?
"%0_%1".format(currentSpace, defaultValue) :
customFields["server.bag"];
this.createRoundel(container, tiddler, currentSpace,
defaultValue, options);
}
},
updateEditFields: function(tiddlerEl, bag) {
var saveBagField = $('[edit="server.bag"]', tiddlerEl),
saveWorkspaceField = $('[edit="server.workspace"]', tiddlerEl),
input = $("<input />").attr("type", "hidden"),
workspace = "bags/" + bag;
if(saveBagField.length === 0) {
input.clone().attr("edit", "server.bag").val(bag).
appendTo(tiddlerEl);
} else {
saveBagField.val(bag);
}
// reset to prevent side effects
$(tiddlerEl).attr("tiddlyFields", "");
if(saveWorkspaceField.length === 0) {
input.clone().attr("edit", "server.workspace").
val(workspace).appendTo(tiddlerEl);
} else {
saveWorkspaceField.val(workspace);
}
},
setBag: function(tiddlerEl, newBag, options) {
var bagStatus,
title = $(tiddlerEl).attr("tiddler"),
tiddler = store.getTiddler(title),
originButton = $(".originButton", tiddlerEl)[0],
refreshIcon,
newWorkspace = "bags/" + newBag,
rPrivate = $("input[type=radio].isPrivate", tiddlerEl),
rPublic = $("input[type=radio].isPublic", tiddlerEl);
refreshIcon = function(type) {
var originMacro = config.macros.tiddlerOrigin;
if(originButton && originMacro) {
options.noclick = true;
originMacro.showPrivacyRoundel(tiddler, type,
originButton, options);
}
};
macro.updateEditFields(tiddlerEl, newBag);
if(tiddler) {
tiddler.fields["server.bag"] = newBag;
// for external tiddlers
tiddler.fields["server.workspace"] = newWorkspace;
}
if(newBag.indexOf("_public") > -1) {
rPrivate.attr("checked", false);
rPublic.attr("checked", true);
bagStatus = "public";
} else {
rPublic.attr("checked", false); // explicitly do this for ie
rPrivate.attr("checked", true);
bagStatus = "private";
}
refreshIcon(bagStatus);
},
createRoundel: function(container, tiddler, currentSpace,
defaultValue, options) {
var privateBag = "%0_private".format(currentSpace),
publicBag = "%0_public".format(currentSpace),
rbtn = $("<input />").attr("type", "radio").
attr("name", tiddler.title),
el = story.findContainingTiddler(container);
rbtn.clone().val("private").addClass("isPrivate").
appendTo(container);
$("<label />").text("private").appendTo(container); // TODO: i18n
rbtn.clone().val("public").addClass("isPublic")
.appendTo(container);
$("<label />").text("public").appendTo(container); // TODO: i18n
$("[type=radio]", container).click(function(ev) {
var btn = $(ev.target);
tiddler.fields["server.page.revision"] = "false";
if(btn.hasClass("isPrivate")) { // private button clicked.
$(el).addClass("isPrivate").removeClass("isPublic");
macro.setBag(el, privateBag, options);
} else {
$(el).addClass("isPublic").removeClass("isPrivate");
macro.setBag(el, publicBag, options);
}
});
window.setTimeout(function() {
macro.setBag(el, defaultValue, options);
}, 100);
// annoyingly this is needed as customFields are added to end of EditTemplate so are not present yet
// and don't seem to respect any existing customFields.
}
};
}(jQuery));
//}}}
in reply to jon's [[April Design - Plugins]]@jon
<<<
* plugins exist but in a much more locked down controlled form
* any initial version wont have plugins for simplicity.
* not clear how to activate plugins yet
<<<
Javascript is designed, to be easily overwritten. So this will be hard to accomplish.
<<<
* one of problems with TiddlyWiki is that one space can behave and look completely different from another space. It's not easy to learn patterns.
<<<
IMO it is a great feature, that you have the freedom to change the layout to your likings. If learning the "pattern" is too difficult, there needs to be better documentation about "best practices". Then I am pretty sure, this is no problem anymore.
<<<
* cannot change core behaviour.
* widget type approach.
* one might swap out certain bits of functionality e.g. wikifier for a LaTeX wikifier or adding a tag cloud to side of notes
<<<
A well designed API + documentation will help to keep things clean. At the moment, TW imo is hard core monkeypatched. The cool thing about this is, that it still works. So there must be something right. The pain starts, if you search for the "right" point to hook your own plugins in.
I think TW macros are "widgets". So I don't see a big difference here.
var user, userbag;
var friends = [];
var host = "http://tiddlyspace.com";
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView", "false");
}
});
function printMessage(txt) {
alert(txt);
}
function printError(txt) {
alert(txt);
}
var simpleDate = (function() {
var measures = {
second: 1,
minute: 60,
hour: 3600,
day: 86400,
week: 604800,
month: 2592000,
year: 31536000
};
var chkMultiple = function(amount, type) {
return (amount > 1) ? amount + " " + type + "s":"a " + type;
};
return function(thedate) {
var dateStr, amount,
current = new Date().getTime(),
diff = (current - thedate.getTime()) / 1000; // work with seconds
if(diff > measures.year) {
amount = Math.round(diff/measures.year);
dateStr = "about " + chkMultiple(amount, "year") + " ago";
} else if(diff > measures.month) {
amount = Math.round(diff/measures.month);
//if(typeof amount == "")
dateStr = "about " + chkMultiple(amount, "month") + " ago";
} else if(diff > measures.week) {
amount = Math.round(diff/measures.week);
dateStr = "about " + chkMultiple(amount, "week") + " ago";
} else if(diff > measures.day) {
amount = Math.round(diff/measures.day);
dateStr = "about " + chkMultiple(amount, "day") + " ago";
} else if(diff > measures.hour) {
amount = Math.round(diff/measures.hour);
dateStr = "about " + chkMultiple(amount, "hour") + " ago";
} else if(diff > measures.minute) {
amount = Math.round(diff/measures.minute);
dateStr = "about " + chkMultiple(amount, "minute") + " ago";
} else {
dateStr = "a few seconds ago";
}
return dateStr;
};
})();
function prettyDate(t) {
var date = new Date(Date.UTC(
parseInt(t.substr(0, 4), 10),
parseInt(t.substr(4, 2), 10) - 1,
parseInt(t.substr(6, 2), 10),
parseInt(t.substr(8, 2), 10),
parseInt(t.substr(10, 2), 10),
parseInt(t.substr(12, 2) || "0", 10),
parseInt(t.substr(14, 3) || "0", 10)
));
return simpleDate(date);
}
function endsWith(str, suffix) {
return str.indexOf(suffix) == str.length - suffix.length;
}
function isShadow(tid) {
var shadows = ["MarkupPreHead", "DefaultTiddlers", "PageTemplate", "SideBarTabs",
"GettingStarted", "MainMenu", "SiteTitle", "SiteSubtitle", "ColorPalette",
"SiteIcon", "ViewTemplate", "EditTemplate", "ServerSettings", "MarkupPostHead",
"MarkupPostBody", "MarkupPreBody"];
return tid.title.indexOf("StyleSheet") === 0 ||
tid.title.indexOf("SideBar") === 0 ||
shadows.indexOf(tid.title) > -1 || endsWith(tid.title, "SetupFlag") ? true : false;
}
function isPlugin(tid) {
return tid.tags.indexOf("systemConfig") > -1 ? true : false;
}
function isArtifact(tid) {
var follow = tid.tags.indexOf("follow") > -1;
var type = tid.type;
if(follow || type) {
return true;
} else {
return false;
}
}
function chooseTiddlers(tiddlers) {
var _tiddlers = [];
for(var i = 0; i < tiddlers.length; i++) {
var tid = tiddlers[i];
if(!isPlugin(tid) && !isShadow(tid) && !isArtifact(tid)) {
_tiddlers.push(tid);
}
}
return _tiddlers;
}
function bubbleDown() {
var friends = $(".friend");
friends.css({ position: "relative" });
var target;
friends.each(function(i, el) {
if(!target && $(el).hasClass("silentFriend") &&
$(el).next(".friend").hasClass("noisyFriend")) {
target = el;
}
});
if(target) {
var other = $(target).next(".friend");
// we want to move target above the prev element
// target is an element which has the class noisy and the previous node is quiet
var swapDuration = 50;
var otherHeight = other.height();
var thisHeight = $(target).height();
$(target).animate({ top: + otherHeight }, { duration: swapDuration });
$(other).animate({ top: - thisHeight }, { duration: swapDuration,
complete: function() {
var newTarget = $(target).clone(true).insertAfter(other)[0];
$(target).remove();
$(other).css({ top: 0 });
$(newTarget).css({ top: 0 });
bubbleDown();
}
});
}
}
function renderTiddlerList(container,friend) {
var tidList = $("<ul />").appendTo(container)[0];
$("<li />").text("loading").appendTo(tidList);
var oncompletion = function() {
if($(".errorFriend,.silentFriend,.noisyFriend").length === $(".friend").length) {
bubbleDown();
}
}
$.ajax({ dataType: "json",
url: "/search?q=modifier:" + friend + "&select=modified:>3d&sort=-modified",
error: function() {
$(container).addClass("errorFriend");
oncompletion();
},
success: function(tiddlers) {
$(tidList).empty();
tiddlers = chooseTiddlers(tiddlers);
if(tiddlers.length === 0) {
$(container).addClass("silentFriend");
$("<li />").text("No recent activity.").appendTo(tidList);
oncompletion();
return;
} else {
$(container).addClass("noisyFriend").removeClass("inactiveFriend");
oncompletion();
}
for(var i=0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var item = $("<li />").appendTo(tidList)[0];
var win;
var space = tiddler.bag.split("_")[0];
var spaceUrl = "http://" + space + ".tiddlyspace.com";
var path = "/bags/" + tiddler.bag + "/tiddlers/" + encodeURIComponent(tiddler.title);
var link = $("<a />").text(tiddler.title).
attr("href", spaceUrl + path).
data("path", path).
click(function(ev) {
var win = $(ev.target).data("win");
if($(ev.target).hasClass("active")) {
$(win).toggle(1000);
} else {
$(ev.target).addClass("active");
$(".text", win).text("loading...");
$(win).show();
$.ajax({
url: $(ev.target).data("path"),
data: {
render: "y"
},
dataType: "json",
success: function(tiddler) {
$(".text",win).html(tiddler.render);
$(win).show(1000);
},
error: function() {
$(".text", win).text("error loading that tiddler");
}
});
}
ev.preventDefault();
}).
appendTo(item)[0];
var space = tiddler.bag.split("_")[0];
$("<span />").text(" in ").appendTo(item);
$("<a />").attr("href", spaceUrl).text(space).appendTo(item);
$("<span />").text(" (" + prettyDate(tiddler.modified) + ")").appendTo(item);
win = $("<div />").addClass("tiddler").appendTo(item)[0];
$("<div />").addClass("text").appendTo(win);
var toolbar = $("<div />").addClass("toolbar").appendTo(win)[0];
var extra = $("<div />").addClass("extra").appendTo(win)[0];
$("<button />").data("bag", tiddler.bag).data("title", tiddler.title).text("give feedback").
data("revision", tiddler.revision).click(function(ev) {
var title = $(ev.target).data("title");
var revision = $(ev.target).data("revision");
var bag = $(ev.target).data("bag");
var revisionURL = host + "/bags/" + bag + "/tiddlers/" + encodeURIComponent(title) + "/revisions/" + revision;
var space = bag.split("_")[0];
var area = $(ev.target).parents(".tiddler").children(".extra")[0];
$(area).hide();
$("<textarea />").appendTo(area);
$("<button />").text("save feedback").click(function(ev) {
var tid = new tiddlyweb.Tiddler("Feedback for " + title, userbag);
tid.tags = ["feedback", "@" + space];
tid.text = ["In reply to [[", title, "]]@", space,
" (revision [[", revision, "|", revisionURL, "]])\n\n"].join("") + $("textarea", area).val();
tid.put(function(tiddler) {
$(area).empty();
$("<span />").text("your comment: ").appendTo(area);
$("<a />").attr("href", "/" + encodeURIComponent(tiddler.title)).text(tiddler.title).appendTo(area);
}, function() {
printError("error commenting!");
});
}).appendTo(area);
$(area).show(1000);
ev.preventDefault();
$(ev.target).remove();
return false;
}).appendTo(toolbar);
$(win).hide();
$(link).data("win", win);
}
}
})
}
function removeFriend(friend) {
var tiddler = new tiddlyweb.Tiddler("@" + friend, userbag);
var success = function() {
printMessage("User removed from friends");
var newFriends = [];
for(var i = 0; i < friends.length; i++) {
var f = friends[i];
if(f !== friend) {
newFriends.push(f);
}
}
friends = newFriends;
$("#friend-" + friend).hide(2000);
};
tiddler["delete"](success, function() {
var old = new tiddlyweb.Tiddler(friend, userbag);
old["delete"](success, function() {
printError("Unable to remove friend " + friend);
})
})
}
function renderFriend(list, friend) {
var bag = friend + "_public";
var item = $("<li />").addClass("friend").attr("id", "friend-" + friend).addClass("inactiveFriend").appendTo(list)[0];
$("<img />").attr("alt", friend).attr("title", friend).
attr("src", host + "/bags/" + bag + "/tiddlers/SiteIcon").css({ width: 48, height: 48 }).appendTo(item);
var heading = $("<h2>").appendTo(item)[0];
$("<a />").attr("href", "#friend-" + friend).attr("name", "friend-" + friend).text(friend).appendTo(heading);
$("<button />").data("who", friend).text("remove from friends").
click(function(ev) {
if(confirm("Are you sure you want to remove " + friend + " as a friend?")) {
removeFriend($(ev.target).data("who"));
}
}).appendTo(item)[0];
renderTiddlerList(item,friend);
}
function renderFriends() {
var list = $("<ul />").appendTo("#friends")[0];
$("<li />").text("Activity of your friends will appear below when available").appendTo(list);
for(var i = 0; i < friends.length; i++) {
var friend = friends[i];
renderFriend(list, friend);
}
}
function followWidget() {
$("#friends").empty();
var container = $("<div />").addClass("addfriends").appendTo("#friends")[0];
$("<input />").attr("name", "friend").appendTo(container);
$("<button />").text("add friend").click(function(ev) {
var friend = $(ev.target).parent().children("[name='friend']").val();
if(friends.indexOf(friend) > -1) {
return printError("You already follow " + friend + "!");
}
var title;
if(friend.indexOf("@") !== 0) {
title = "@" + friend;
} else {
title = friend;
}
$.ajax({ dataType: "text", url: "/users/" + friend,
success: function() {
var tid = new tiddlyweb.Tiddler(title, userbag);
tid.tags = ["follow", "excludeLists"];
tid.put(function(tiddler) {
printMessage("Added friend " + friend);
renderFriend($("#friends ul")[0], friend);
window.location.hash = "#friend-" + friend;
}, function() {
printError("Failed to add friend " + friend);
})
},
error: function() {
printError("No one with name " + friend + " exists!");
}
});
}).appendTo(container);
renderFriends();
}
$.ajax({
url: "/status",
dataType: "json",
success: function(status) {
user = status.username;
userbag = new tiddlyweb.Bag(user + "_public", "/");
$.ajax({ url: "/bags/" + user + "_public/tiddlers?select=tag:follow", dataType: "json", success: function(tiddlers) {
for(var i = 0; i < tiddlers.length; i++) {
var title = tiddlers[i].title;
if(title.indexOf("@") === 0) {
title = title.substr(1, title.length);
}
friends.push(title);
}
friends.sort();
followWidget();
}
});
}
})
In reply to bauwe: [[Simplicity a TiddlySpace]]@bauwebijl
<<<
When the left and right nav buttons are invisible, how could a reader know that here are more tiddlers to read? (perhaps that middle strip might give an indication if always visible ... or a "you are here"....or pagenumbers "page 2 of 10")
<<<
You are right, especitally visited with an iPad it doesn't work well that way.
So I changed it: now it's initial opacity is 40%. Hovering is 100%. But still gray.
<<<
In backstage: When I want to access the tiddlers via backstagePanel the tabs are hard to use (jumpy)...almost not possible to select a tab from the side.
<<<
Need to check the backstage/sidebar's CSS.
@@color:lightGrey;background-color:lightGrey; For TW editing use paramifyer - #txtTheme:~NostalgiaSimplicity@@
<<<
Perhaps an idea to present the tiddlers in a carousel (like the lightbox)...and provide scrollwheel browsing (if tiddlers are limited to max. 10 or 20...)...?
<<<
May be some more eye-candy as add on.
----
In reply to kosmaton: [[Simplicity a TiddlySpace]]@kosmaton
<<<
*"The tiddler 'Page (10)' doesn't yet exist. Double-click to create it". Double-click does nothing (at least in my FF): confusing for newcomers? Best change the message.
<<<
* I changed the behaviour of the system. Now pages are created with at least 3 digits.
** I hope nobody will ever have 999+ tiddlers with this system :)
** Sorting Page (1), Page (10) should be no problem now.
* Text is now: "Your text comes here!", if a new page is created.
<<<
*Tiddler area width does not seem to resize beneath some threshold? Maybe intentional.
<<<
{{{width: 780px}}} by intention
<<<
*What if you want to //insert// a page... say you have 40 pages and you realise you missed a substantial bit early on.
<<<
* As I wrote "About 1-10 pages" :) but ... I am planing to have AddOns, which can enable the full power by space inclusion ...
* But, for the beginning, people should ask for more, because they need it. (Search for the existing easter egg:)
<<<
*I like the 'elevator buttons'. But maybe they make the actual tabs ('Page (x)' etc.) unnecessary. Especially if you cannot change the name of the pages/tiddlers.
<<<
*The "elevator buttons" are visible for guests and the owner.
*The tab is only visible for the owner. I thought it would be easier, to navigate in edit mode.
*We'll see ....
<<<
*I wonder if it is not too simplistic that you can't change the names of the pages. A book has pages, but it usually also has chapter titles. There is no interface for chapters here...?
<<<
Yes it is: !Heading 1
<<<
*No "Close all"? (I know you can 'close all others' via the tabs, but still.) Or indeed "Open all": that would make it more like a book, in which you pick a page to read.
<<<
* Tabs are only visible for the owner/editor.
* As you said "Click a tab" - "Click it again" - "Close the last tab"
* I know: 3 clicks to 1 but much more interface needed.
* We'll see...
<<<
* If you closed all tiddlers/pages, including 'Page', you have to reload to get the story back, or create a new page... not ideal?
<<<
* --Right. Need to think about this.--
* I created a little home icon top right, which jumps to {{{[[Page (001)]]}}}
----
Initial post
Hi Folks,
* I am happy to announce @Simplicity a minimalistic space.
* It should attract TiddlyWiki / TiddlySpace first time users.
* It is intended to publish _linear_ text pages, with a minimal number of subpages ~1-10 but using the full power of TiddlyWiki. (CamelCase linking, which brings back the non-linear behaviour).
* If you need a new main title, create a new space.
* The browser "back/forward" buttons work.
* Edit mode is minimalistic too. Try it, and you'll see :)
* Simplicity can clone itself into a new space. It is not intended to be included into other spaces. It's no theme!
* The only thing, that's not minimalistic, at the moment, is it's download size :)
** suggestions welcome.
Tell me, what you think.
-mario
<<tiddler FollowTemplate>>
I want to read it the TW way, like so: http://pmario.tiddlyspace.com/#TiddlySpaceGoals
twrelease_: beta
external_: true
<<tiddler FollowTemplate>>
/***
|''Name''|ErrorHandlerPlugin|
|''Version''|0.4.3|
|''Author''|Jon Robson|
|''Description''|Localised tiddler save errors including edit conflict resolution.|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig|
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace;
var currentSpace = tiddlyspace.currentSpace.name;
tiddlyspace.getLocalTitle = function(title, workspace, suffix) {
var endsWith = config.extensions.BinaryTiddlersPlugin.endsWith;
if(!suffix) {
var isPublic = endsWith(workspace, "_public");
suffix = tiddlyspace.resolveSpaceName(workspace);
if(currentSpace == suffix) {
suffix = isPublic ? "public" : "private";
} else {
suffix = "@%0".format(suffix);
}
}
return "%0 *(%1)*".format(title, suffix);
};
var sssp = config.extensions.ServerSideSavingPlugin;
var msgs = config.messages.editConflict = {
loading: "Loading..",
resolve: "[[Edit Conflict]]@glossary: this tiddler may have been changed by someone else.",
reviewDiff: "review (recommended)",
reviewDiffTooltip: "review changes made to this tiddler",
reviewDiffError: "error retrieving revision.",
save: "overwrite",
saveTooltip: "make this revision the top revision of this tiddler",
discard: "cancel",
discardTooltip: "undo changes to this tiddler and get most recent version",
diffTitle: "%0",
diffFieldTitle: "%0 - fields",
diffTextTitle: "%0 - text",
updating: "updating your version...",
diffHeader: ["Review the changes that have been made whilst you were editing this tiddler. ",
"Fold relevant changes back into your version.\n",
"{{removed{Red}}} highlight shows content removed. ",
"{{added{Green}}} highlight shows content added.\n"].join(""),
diffTextHeader: "View changes in text",
diffFieldsHeader: "View changes in fields"
};
var plugin = config.extensions.errorHandler = {
diffTags: ["excludeLists", "excludeMissing", "excludeSearch"],
displayMessage: function(message, tiddler, context) {
var desc = context && context.httpStatus ? context.statusText :
sssp.locale.connectionError;
var reportArea = plugin.reportError(tiddler.title);
var msg = $("<div />").appendTo(reportArea);
if(message == "saveConflict") {
wikify(msgs.resolve, msg[0]);
var choiceArea = $("<div />").appendTo(reportArea)[0];
plugin.editConflictHandler(choiceArea, tiddler);
} else {
msg.text(sssp.locale[message].format(tiddler.title, desc));
}
},
editConflictHandler: function(container, tiddler) {
var title = tiddler.title;
var myrev = tiddler.fields["server.page.revision"];
// note user now needs to edit, fix problem and save.
// TODO: make sure this gets reset in save callback
store.getTiddler(title).fields["server.page.revision"] = "false";
var diffBtn = createTiddlyButton(container, msgs.reviewDiff, msgs.reviewDiffTooltip, function(ev) {
var title = $(ev.target).data("title");
plugin.displayDiff(ev.target, store.getTiddler(title), myrev);
});
var saveBtn = createTiddlyButton(container, msgs.save, msgs.saveTooltip, function(ev) {
var title = $(ev.target).data("title");
var tid = store.saveTiddler(store.getTiddler(title));
autoSaveChanges(null, [tid]);
});
var ignoreBtn = createTiddlyButton(container, msgs.discard, msgs.discardTooltip, function(ev) {
var title = $(ev.target).text(msgs.updating).data("title");
plugin.resetToServerVersion(store.getTiddler(title));
});
$([diffBtn, ignoreBtn, saveBtn]).data("title", title);
},
getDiffTiddlerTexts: function(diffText) {
var chunks = diffText.split("\n \n");
if(chunks.length < 2) {
return [chunks[0], ""];
} else {
var diffFieldsText = "{{diff{\n%0\n}}}".format(chunks[0]);
diffText = '{{diff{\n%0\n}}}'.format(chunks.splice(1, chunks.length).join("\n"));
return [diffText, diffFieldsText];
}
},
makeDiffTiddler: function(title, diff) {
var newTiddler = new Tiddler(title);
var tags = plugin.diffTags;
newTiddler.text = msgs.loading;
newTiddler.fields.doNotSave = true;
newTiddler.tags = diff ? tags.concat(["diff"]) : tags;
newTiddler = store.saveTiddler(newTiddler);
$.extend(store.getTiddler(title).fields,
config.defaultCustomFields); // allow option to save it
return newTiddler;
},
displayDiff: function(src, tiddler, latestRevision) {
var adaptor = tiddler.getAdaptor();
var title = tiddler.title;
var ts = new Date().formatString("0hh:0mm:0ss");
var suffix = "edit conflict %0".format(ts);
var diffTitle = tiddlyspace.getLocalTitle(msgs.diffTitle.format(title), "", suffix);
var diffTextTitle = tiddlyspace.getLocalTitle(msgs.diffTextTitle.format(title), "", suffix);
var diffFieldsTitle = tiddlyspace.getLocalTitle(msgs.diffFieldTitle.format(title), "", suffix);
plugin.makeDiffTiddler(diffTextTitle, true);
plugin.makeDiffTiddler(diffFieldsTitle, true);
var newTiddler = plugin.makeDiffTiddler(diffTitle, false);
newTiddler.text = ['%0\n<<slider chkViewDiffText "%1" "%2">>\n',
'<<slider chkViewDiffField "%3" "%4">>'].join("").
format(msgs.diffHeader, diffTextTitle, msgs.diffTextHeader,
diffFieldsTitle, msgs.diffFieldsHeader);
store.saveTiddler(newTiddler);
var callback = function(r) {
var text = plugin.getDiffTiddlerTexts(r);
store.getTiddler(diffTextTitle).text = text[0];
store.getTiddler(diffFieldsTitle).text = text[1];
story.refreshTiddler(diffTitle, null, true);
};
var workspace = "bags/%0".format(tiddler.fields["server.bag"]);
ajaxReq({
type: "get",
dataType: "text",
url: "/diff?format=unified&rev1=%0/%1/%2&rev2=%0/%1".format(workspace, title, latestRevision),
success: callback,
error: function() {
displayMessage(msgs.reviewDiffError);
}
});
story.displayTiddler(src, diffTitle);
},
resetToServerVersion: function(tiddler) {
var adaptor = tiddler.getAdaptor();
var ctx = {
host: tiddler.fields["server.host"],
workspace: "bags/" + tiddler.fields["server.bag"]
};
adaptor.getTiddler(tiddler.title, ctx, null, function(context) {
store.saveTiddler(context.tiddler);
story.refreshTiddler(tiddler.title);
store.setDirty(false);
});
},
reportError: function(title) {
var el = story.getTiddler(title);
if(!el) {
el = story.displayTiddler(null, title);
}
return $("<div />").addClass("error annotation").prependTo(el)[0];
}
};
sssp.reportFailure = function(message, tiddler, context) {
config.options.chkViewDiffText = config.options.chkViewDiffText === undefined ?
true : config.options.chkViewDiffText;
config.options.chkViewDiffFields = config.options.chkViewDiffFields || false;
plugin.displayMessage(message, tiddler, context);
};
})(jQuery);
//}}}
/***
|''Requires''|codemirror.js|
|''License''|[[codemirror.js]]|
***/
//{{{
CodeMirror.defineMode("css",function(e){function r(e,t){return n=t,e}function i(e,t){var n=e.next();if(n=="@")return e.eatWhile(/[\w\\\-]/),r("meta",e.current());if(n=="/"&&e.eat("*"))return t.tokenize=s,s(e,t);if(n=="<"&&e.eat("!"))return t.tokenize=o,o(e,t);if(n!="=")return n!="~"&&n!="|"||!e.eat("=")?n=='"'||n=="'"?(t.tokenize=u(n),t.tokenize(e,t)):n=="#"?(e.eatWhile(/[\w\\\-]/),r("atom","hash")):n=="!"?(e.match(/^\s*\w*/),r("keyword","important")):/\d/.test(n)?(e.eatWhile(/[\w.%]/),r("number","unit")):/[,.+>*\/]/.test(n)?r(null,"select-op"):/[;{}:\[\]]/.test(n)?r(null,n):(e.eatWhile(/[\w\\\-]/),r("variable","variable")):r(null,"compare");r(null,"compare")}function s(e,t){var n=!1,s;while((s=e.next())!=null){if(n&&s=="/"){t.tokenize=i;break}n=s=="*"}return r("comment","comment")}function o(e,t){var n=0,s;while((s=e.next())!=null){if(n>=2&&s==">"){t.tokenize=i;break}n=s=="-"?n+1:0}return r("comment","comment")}function u(e){return function(t,n){var s=!1,o;while((o=t.next())!=null){if(o==e&&!s)break;s=!s&&o=="\\"}return s||(n.tokenize=i),r("string","string")}}var t=e.indentUnit,n;return{startState:function(e){return{tokenize:i,baseIndent:e||0,stack:[]}},token:function(e,t){if(e.eatSpace())return null;var r=t.tokenize(e,t),i=t.stack[t.stack.length-1];if(n=="hash"&&i!="rule")r="string-2";else if(r=="variable")if(i=="rule")r="number";else if(!i||i=="@media{")r="tag";return i=="rule"&&/^[\{\};]$/.test(n)&&t.stack.pop(),n=="{"?i=="@media"?t.stack[t.stack.length-1]="@media{":t.stack.push("{"):n=="}"?t.stack.pop():n=="@media"?t.stack.push("@media"):i=="{"&&n!="comment"&&t.stack.push("rule"),r},indent:function(e,n){var r=e.stack.length;return/^\}/.test(n)&&(r-=e.stack[e.stack.length-1]=="rule"?2:1),e.baseIndent+r*t},electricChars:"}"}}),CodeMirror.defineMIME("text/css","css");
//}}}
in reply to [[A reply button]]@jermolene
<<<
This can be done using a paramifier like so:
{{{
http://jermolene.tiddlyspace.com/#newTiddler:[[A reply button]]
}}}
See http://www.tiddlywiki.com/#StartupParameters for details.
<<<
That's cool, but I think a new ~StartupCommand ''{{{#reply:[[A reply button]]@cdent}}}'' that loads the tiddler + content from cdent's space and opens it for editing would be cooler :)
{{{
http://jermolene.tiddlyspace.com/#reply:[[A reply button]]@cdent
}}}
! Toolbar Icons Versa Text
I personally prefere icons over text as toolbar commands, because icons are language independent and - I created them :)
! Nostalgia Theme
I actually created a theme, that works with text only menues but it has a slightly different behaviour too. It can be found at: http://nostalgia.tiddlyspace.com/
----
In response to [[icons v. words as toolbar commands]]@stevesuny ~@stevesuny
/***
|''Name''|TiddlySpaceTiddlerIconsPlugin|
|''Version''|0.8.10|
|''Status''|@@beta@@|
|''Author''|Jon Robson|
|''Description''|Provides ability to render SiteIcons and icons that correspond to the home location of given tiddlers|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceTiddlerIconsPlugin.js|
|''Requires''|TiddlySpaceConfig BinaryTiddlersPlugin ImageMacroPlugin TiddlySpacePublishingCommands|
!Notes
{{{<<tiddlerOrigin>>}}} shows the origin of the tiddler it is being run on.
In TiddlySpace terms this means it will determine whether the tiddler is external, public or private.
Where private it will analyse whether a public version exists and distinguish between the different scenarios.
If a tiddler is external, the SiteIcon of that external space will be shown
!Parameters
width / height : define a width or height of the outputted icon
label: if label parameter is set to yes, a label will accompany the icon.
!Code
***/
//{{{
(function($) {
if(!config.macros.image) {
throw "Missing dependency: ImageMacroPlugin";
}
var imageMacro = config.macros.image;
var tiddlyspace = config.extensions.tiddlyspace;
var tweb = config.extensions.tiddlyweb;
var cmds = config.commands;
var cmd = cmds.publishTiddler;
tiddlyspace.resolveSpaceName = function(value) {
var endsWith = config.extensions.BinaryTiddlersPlugin.endsWith;
if(value) {
value = value.indexOf("bags/") === 0 ? value.substr(5) : value;
value = value.indexOf("recipes/") === 0 ? value.substr(8) : value;
if(value.indexOf("@") === 0) {
value = value.substr(1);
}
if(endsWith(value, "_public")) {
value = value.substr(0, value.length - 7);
} else if(endsWith(value, "_private")) {
value = value.substr(0, value.length - 8);
}
value = value.toLowerCase();
}
return value;
};
tiddlyspace.renderAvatar = function(place, value, options) {
options = options ? options : {};
options.labelOptions = options.labelOptions ? options.labelOptions : { include: false, height: 48, width: 48 };
options.imageOptions = options.imageOptions ? options.imageOptions : {};
options.imageOptions.altImage = "/bags/common/tiddlers/defaultUserIcon";
var container = $('<div class="siteIcon" />').appendTo(place);
value = tiddlyspace.resolveSpaceName(value);
tweb.getStatus(function(status) {
var link, noLabel;
if(!value || value == config.views.wikified.defaultModifier ||
value == config.views.wikified.shadowModifier) {
var icon = config.views.wikified.shadowModifier == value ? "shadowIcon" : "missingIcon";
if(store.tiddlerExists(icon)) {
imageMacro.renderImage(container, icon, options.imageOptions);
} else {
noLabel = true;
}
} else {
var spaceURI;
if(value != tiddlyspace.currentSpace.name) {
spaceURI = options.notSpace ? tiddlyspace.getHost(status.server_host) :
tiddlyspace.getHost(status.server_host, value);
}
link = spaceURI ? $("<a />").attr("href", spaceURI) : $("<span />");
link.text(value);
var imageOptions = options.imageOptions;
if(options.spaceLink && !imageOptions.link) {
imageOptions.link = spaceURI;
}
var avatar = options.notSpace ? false : value;
var uri = tiddlyspace.getAvatar(status.server_host, avatar);
imageMacro.renderImage(container, uri, options.imageOptions);
if(!value) {
value = "tiddlyspace";
}
}
if(!noLabel && options.labelOptions.include) {
var prefix = $("<span />").text(options.labelOptions.prefix || "")[0];
var suffix = $("<span />").text(options.labelOptions.suffix || "")[0];
$('<div class="label" />').append(prefix).append(link).
append(suffix).appendTo(container);
}
});
if(value) {
var prefix = options.labelOptions.prefix || "";
var suffix = options.labelOptions.suffix || "";
var label = "%0%1%2".format(prefix, value, suffix);
$(container).attr("title", label);
}
};
var originMacro = config.macros.tiddlerOrigin = {
locale: {
"shadow": "shadow tiddler",
"missing": "missing tiddler",
"private": "private",
"unknown": "unknown state",
"public": "public",
"unsyncedPrivate": "unsynced and private",
"unsyncedPublic": "unsynced and public",
externalPrefix: "from ",
externalBagSuffix: " bag",
externalSuffix: " space",
publishPrivateDeletePrivate: "Are you sure you want to make this tiddler public?",
moveToPrivate: "Are you sure you want to make this tiddler private? Only members will be able to see it.",
pleaseWait: "please wait..",
keepPublic: "keep public",
cannotPublishDirtyTiddler: "The current tiddler is unsaved so cannot be published. Please save the tiddler first.",
keepPrivate: "keep private",
makePublic: "make public",
makePrivate: "make private"
},
handler: function(place, macroName, params,wikifier, paramString, tiddler){
var adaptor = tiddler.getAdaptor();
var btn = $("<div />").addClass("originButton").attr("params", paramString).
attr("refresh", "macro").attr("macroName", macroName).appendTo(place)[0];
$(btn).data("tiddler", tiddler);
originMacro.refresh(btn);
},
refresh: function(btn) {
$(btn).empty();
var paramString = $(btn).attr("params");
var tiddler = $(btn).data("tiddler");
var options = originMacro.getOptions(paramString);
var type = tiddlyspace.getTiddlerStatusType(tiddler);
originMacro.renderIcon(tiddler, type, btn, options);
},
getOptions: function(paramString) {
paramString = "%0 label:no width:48 height:48 spaceLink:yes preserveAspectRatio:yes".format(paramString);
var parsedParams = paramString.parseParams("name");
var params = parsedParams[0].name;
var options = {
labelOptions: originMacro._getLabelOptions(parsedParams),
imageOptions: imageMacro.getArguments(paramString, []),
noclick: parsedParams[0].interactive &&
parsedParams[0].interactive[0] == "no" ? true : false
};
if(!options.noclick) {
var spaceLink = parsedParams[0].spaceLink;
options.spaceLink = spaceLink && spaceLink[0] == "no" ? false : true;
} else {
options.spaceLink = false;
}
return options;
},
_getLabelOptions: function(parsedParams) {
parsedParams = parsedParams[0];
var includeLabel = !parsedParams.label || ( parsedParams.label && parsedParams.label[0] == "yes" );
var prefix = parsedParams.labelPrefix ? parsedParams.labelPrefix[0] : false;
var suffix = parsedParams.labelSuffix ? parsedParams.labelSuffix[0] : false;
return { include: includeLabel, suffix: suffix, prefix: prefix };
},
_isSpace: function(value) {
value = value ? value : "";
var endsWith = config.extensions.BinaryTiddlersPlugin.endsWith;
if(endsWith(value, "_private") || endsWith(value, "_public")) {
return true;
} else {
return false;
}
},
renderIcon: function(tiddler, type, button, options) {
var locale = originMacro.locale;
originMacro.annotateTiddler(button, type);
if(type != "external") {
originMacro.showPrivacyRoundel(tiddler, type, button,
options);
} else {
var prefix = options.labelOptions.prefix, suffix = options.labelOptions.suffix;
var space = tiddler.fields["server.bag"];
options.notSpace = !originMacro._isSpace(space);
options.labelOptions.prefix = prefix ? prefix : locale.externalPrefix;
options.labelOptions.suffix = suffix ? suffix : (options.notSpace ? locale.externalBagSuffix : locale.externalSuffix);
tiddlyspace.renderAvatar(button, space, options);
}
},
showPrivacyRoundel: function(thisTiddler, privacyType, button, options) {
// there is a public tiddler as well as the current tiddler!
// TODO: not this is not enough.. we also need to check if the public tiddler is the same as..
// .. the private tiddler to determine whether this is a draft
// use of hashes would be useful here.
$(button).empty();
var icon = "%0Icon".format(privacyType);
if(privacyType.indexOf("unsynced") === 0 && !store.tiddlerExists(icon)) {
icon = "unsyncedIcon";
}
if(privacyType == "shadow") {
if(!store.tiddlerExists(icon)) {
icon = "bags/tiddlyspace/tiddlers/SiteIcon";
}
}
if(privacyType == "missing" && !store.tiddlerExists(icon)) {
return; // the user is not making use of the missingIcon
} else {
imageMacro.renderImage(button, icon, options.imageOptions);
originMacro.showLabel(button, privacyType, options.labelOptions);
var cmd = originMacro.iconCommands[privacyType];
if(cmd && thisTiddler && !options.noclick) {
$(button).click(function(ev) {
cmd(ev, thisTiddler);
});
}
}
},
annotateTiddler: function(place, type) {
var tidEl = $(story.findContainingTiddler(place));
tidEl.
removeClass("private public external privateAndPublic privateNotPublic shadow").
addClass(type);
},
showLabel: function(button, type, options) {
var locale = originMacro.locale;
var label = options.label ? options.label : locale[type];
label = label ? label : locale.unknown;
if(options && options.include) {
$('<div class="roundelLabel" />').html(label).appendTo(button);
}
$(button).attr("title", label);
},
confirm: function(ev, msg, onYes, options) {
options = options ? options : {};
onYes = onYes ? onYes : function(ev) {};
var btn = $(".originButton", $(ev.target).parents())[0];
var popup = Popup.create(btn);
$(popup).addClass("confirmationPopup");
$("<div />").addClass("message").text(msg).appendTo(popup);
$("<button />").addClass("button").text(options.yesLabel || "yes").appendTo(popup).click(onYes);
$("<button />").addClass("button").text(options.noLabel || "no").click(function(ev) {
Popup.remove();
}).appendTo(popup);
Popup.show();
ev.stopPropagation();
return false;
},
alert: function(ev, msg) {
var popup = Popup.create(ev.target);
$(popup).addClass("confirmationPopup alert");
$("<div />").addClass("message").text(msg).appendTo(popup);
Popup.show();
ev.stopPropagation();
},
reportDirty: function(el) {
originMacro.alert(el, originMacro.locale.cannotPublishDirtyTiddler);
},
iconCommands: {
"public": function(ev, tiddler) {
if(!readOnly) {
var locale = originMacro.locale;
var msg = locale.moveToPrivate;
if(story.isDirty(tiddler.title)) {
originMacro.reportDirty(ev);
} else {
originMacro.confirm(ev, msg, function(ev) {
var target = $(ev.target);
var onComplete = function(info) {};
var privateBag = cmd.toggleBag(tiddler, "private");
cmd.moveTiddler(tiddler, {
title: tiddler.title,
fields: { "server.bag": privateBag }
}, onComplete);
}, { yesLabel: locale.makePrivate, noLabel: locale.keepPublic });
}
}
},
"private": function(ev, tiddler) {
if(!readOnly) {
var locale = originMacro.locale;
var adaptor = tiddler.getAdaptor();
var publishTo = tiddler.fields["publish.name"] || tiddler.title;
var workspace = "bags/%0".format(tiddler.fields["server.bag"]);
tiddler.fields["server.workspace"] = workspace;
var publicBag = cmd.toggleBag(tiddler, "public");
var msg;
msg = locale.publishPrivateDeletePrivate;
var title = tiddler.title;
var newTitle = publishTo || tiddler.title;
tiddler.fields["server.page.revision"] = "false";
store.addTiddler(tiddler);
if(story.isDirty(tiddler.title)) {
originMacro.reportDirty(ev);
} else {
originMacro.confirm(ev, msg, function(ev) {
var onComplete = function(info) {};
cmd.moveTiddler(tiddler, {
title: newTitle,
fields: { "server.bag": publicBag }
}, onComplete);
}, { yesLabel: locale.makePublic, noLabel: locale.keepPrivate });
}
}
}
}
};
})(jQuery);
//}}}
2010.09.29
new tags only
----
----
2010.09.24
!ability to filter results
<<<
pmario suggested he would like to filter activity results (I guess like the MySpaces plugin). If activity feed items are tiddlers this becomes a lot easier to be supported via macros.
<<<
Not really.
What I want is: default is true.
<<option chkxx>> show plugin
<<option chkxx>> show shadow
<<option chkxx>> show standard
<<option chkxx>> show follow
<<option chkxx>> show followYou
<<option chkxx>> show siteIcon
<<option chkxx>> show siteInfo
<<option chkxx>> show ownSiteIcon
<<option chkxx>> show notify
<<option chkxx>> show reply
<<option txtxx>> show me x days. No matter how many entries.
<<option txtxx>> limit to max lines. If set the above is limited.
[[Button: get activity according to the above settings]]
If full list is shown, the text below auto filters the list again after eg: 3 chares typed in.
<<option txtxx>> filter text
!activity macro feature request
{{{<<activity scan:@all tag:@pmario>>}}} .. Scans every spaces, that I don't follow, if tiddlers are tagged @pmario.
would make
{{{<<activity scan:@jon tag:@pmario>>}}} .. options from above are ignored. If list is displayed filter text is active.
----
----
!OLD
First off all, I want tho know. Are the {{{@anyName}}} tags needed?
And what are they good for?
!{{{@username}}} rather than username
<<<
..<snip> For the purpose of backwards compatibility we could have a grace period which uses both, but it would be good to tie down these conventions early.
<<<
It would be good to change it early, if changed.
!a more button
<<<
Tied in with the above, in some cases I might want to go even further down the activity stream on a busy day (currently it shows the most recent 50 but I might want to see the 50 before that).
<<<
And an textinput filter + a [Clear filtertext] button.
line: "jon modified a tiddler Some more following thoughts in the jon space. respond (<14:01 23/09>)"
If one of the following text snippets fits a line it is displayed.
"jon", "modified", "modifi", "Some more", "thoughts", "23/09",
!Activity alerts
<<<
I would like the activity stream to pick up any tiddlers tagged @jon even if I don't follow the person they originate from. This would allow users to target messages at me even if I am not following them and for me to discover them and read their important message. It might be useful in a [[TiddlyWorld environment|http://tiddlyworld.tiddlyspace.com/]] and for new people to TiddlySpace getting their views heard.
<<<
+1
!Question
If I want to use my homespace only as a presentaiton space for my TiddlySpace projects. I don't want to publish decussion tiddlers there
How can I manage this.
!Issue
*I did open the "{{{Some more following thoughts [@jon]}}}" tiddler and edited it.
*Save -> OK
*Edit it again. won't save. because of "donotsave" custom field.
**This one should be deleted if an alien tiddler is locally saved.
!Others say
<<tsScan [[Some more following thoughts]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
in reply to @jermolene:
<<<
!!Notes
//@jermolene says://
<<<
>It's important to stick to the idea that the subscriber is control when they include a space. The publisher decides what to publish, not what people can do with it.
I think both sides, have to have the freedom to decide what's going on. Licenses like: MIT, BSD, GPL, CC and others, make this possible.
>Within that constraint, this story could be accomplished by (a) deciding a convention for marking content as //not intended for inclusion// and (b) adopting that convention by default in the machinery for including spaces.
My first impression is, that it could work that way.
/***
|''Name''|ServerSideSavingPlugin|
|''Description''|server-side saving|
|''Author''|FND|
|''Version''|0.6.5|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/plugins/ServerSideSavingPlugin.js|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5.3|
|''Keywords''|serverSide|
!Notes
This plugin relies on a dedicated adaptor to be present.
The specific nature of this plugin depends on the respective server.
!Revision History
!!v0.1 (2008-11-24)
* initial release
!!v0.2 (2008-12-01)
* added support for local saving
!!v0.3 (2008-12-03)
* added Save to Web macro for manual synchronization
!!v0.4 (2009-01-15)
* removed ServerConfig dependency by detecting server type from the respective tiddlers
!!v0.5 (2009-08-25)
* raised CoreVersion to 2.5.3 to take advantage of core fixes
!!v0.6 (2010-04-21)
* added notification about cross-domain restrictions to ImportTiddlers
!To Do
* conflict detection/resolution
* rename to ServerLinkPlugin?
* document deletion/renaming convention
!Code
***/
//{{{
(function($) {
readOnly = false; //# enable editing over HTTP
var plugin = config.extensions.ServerSideSavingPlugin = {};
plugin.locale = {
saved: "%0 saved successfully",
saveError: "Error saving %0: %1",
saveConflict: "Error saving %0: edit conflict",
deleted: "Removed %0",
deleteError: "Error removing %0: %1",
deleteLocalError: "Error removing %0 locally",
removedNotice: "This tiddler has been deleted.",
connectionError: "connection could not be established",
hostError: "Unable to import from this location due to cross-domain restrictions."
};
plugin.sync = function(tiddlers) {
tiddlers = tiddlers && tiddlers[0] ? tiddlers : store.getTiddlers();
$.each(tiddlers, function(i, tiddler) {
var changecount = parseInt(tiddler.fields.changecount, 10);
if(tiddler.fields.deleted === "true" && changecount === 1) {
plugin.removeTiddler(tiddler);
} else if(tiddler.isTouched() && !tiddler.doNotSave() &&
tiddler.getServerType() && tiddler.fields["server.host"]) { // XXX: server.host could be empty string
delete tiddler.fields.deleted;
plugin.saveTiddler(tiddler);
}
});
};
plugin.saveTiddler = function(tiddler) {
try {
var adaptor = this.getTiddlerServerAdaptor(tiddler);
} catch(ex) {
return false;
}
var context = {
tiddler: tiddler,
changecount: tiddler.fields.changecount,
workspace: tiddler.fields["server.workspace"]
};
var serverTitle = tiddler.fields["server.title"]; // indicates renames
if(!serverTitle) {
tiddler.fields["server.title"] = tiddler.title;
} else if(tiddler.title != serverTitle) {
return adaptor.moveTiddler({ title: serverTitle },
{ title: tiddler.title }, context, null, this.saveTiddlerCallback);
}
var req = adaptor.putTiddler(tiddler, context, {}, this.saveTiddlerCallback);
return req ? tiddler : false;
};
plugin.saveTiddlerCallback = function(context, userParams) {
var tiddler = context.tiddler;
if(context.status) {
if(tiddler.fields.changecount == context.changecount) { //# check for changes since save was triggered
tiddler.clearChangeCount();
} else if(tiddler.fields.changecount > 0) {
tiddler.fields.changecount -= context.changecount;
}
plugin.reportSuccess("saved", tiddler);
store.setDirty(false);
} else {
if(context.httpStatus == 412) {
plugin.reportFailure("saveConflict", tiddler);
} else {
plugin.reportFailure("saveError", tiddler, context);
}
}
};
plugin.removeTiddler = function(tiddler) {
try {
var adaptor = this.getTiddlerServerAdaptor(tiddler);
} catch(ex) {
return false;
}
var context = {
host: tiddler.fields["server.host"],
workspace: tiddler.fields["server.workspace"],
tiddler: tiddler
};
var req = adaptor.deleteTiddler(tiddler, context, {}, this.removeTiddlerCallback);
return req ? tiddler : false;
};
plugin.removeTiddlerCallback = function(context, userParams) {
var tiddler = context.tiddler;
if(context.status) {
if(tiddler.fields.deleted === "true") {
store.deleteTiddler(tiddler.title);
} else {
plugin.reportFailure("deleteLocalError", tiddler);
}
plugin.reportSuccess("deleted", tiddler);
store.setDirty(false);
} else {
plugin.reportFailure("deleteError", tiddler, context);
}
};
plugin.getTiddlerServerAdaptor = function(tiddler) { // XXX: rename?
var type = tiddler.fields["server.type"] || config.defaultCustomFields["server.type"];
return new config.adaptors[type]();
};
plugin.reportSuccess = function(msg, tiddler) {
displayMessage(plugin.locale[msg].format([tiddler.title]));
};
plugin.reportFailure = function(msg, tiddler, context) {
var desc = (context && context.httpStatus) ? context.statusText :
plugin.locale.connectionError;
displayMessage(plugin.locale[msg].format([tiddler.title, desc]));
};
config.macros.saveToWeb = { // XXX: hijack existing sync macro?
locale: { // TODO: merge with plugin.locale?
btnLabel: "save to web",
btnTooltip: "synchronize changes",
btnAccessKey: null
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
createTiddlyButton(place, this.locale.btnLabel, this.locale.btnTooltip,
plugin.sync, null, null, this.locale.btnAccessKey);
}
};
// hijack saveChanges to trigger remote saving
var _saveChanges = saveChanges;
saveChanges = function(onlyIfDirty, tiddlers) {
if(window.location.protocol == "file:") {
_saveChanges.apply(this, arguments);
} else {
plugin.sync(tiddlers);
}
};
// override removeTiddler to flag tiddler as deleted -- XXX: use hijack to preserve compatibility?
TiddlyWiki.prototype.removeTiddler = function(title) { // XXX: should override deleteTiddler instance method?
var tiddler = this.fetchTiddler(title);
if(tiddler) {
tiddler.tags = ["excludeLists", "excludeSearch", "excludeMissing"];
tiddler.text = plugin.locale.removedNotice;
tiddler.fields.deleted = "true"; // XXX: rename to removed/tiddlerRemoved?
tiddler.fields.changecount = "1";
this.notify(title, true);
this.setDirty(true);
}
};
// hijack ImportTiddlers wizard to handle cross-domain restrictions
var _onOpen = config.macros.importTiddlers.onOpen;
config.macros.importTiddlers.onOpen = function(ev) {
var btn = $(resolveTarget(ev));
var url = btn.closest(".wizard").find("input[name=txtPath]").val();
if(window.location.protocol != "file:" && url.indexOf("://") != -1) {
var host = url.split("/")[2];
var macro = config.macros.importTiddlers;
if(host != window.location.host) {
btn.text(macro.cancelLabel).attr("title", macro.cancelPrompt);
btn[0].onclick = macro.onCancel;
$('<span class="status" />').text(plugin.locale.hostError).insertAfter(btn);
return false;
}
}
return _onOpen.apply(this, arguments);
};
})(jQuery);
//}}}
/***
|''Name''|GroupByPlugin|
|''Description''|Mimics allTags macro to provide ways of creating lists grouping tiddlers by any field|
|''Version''|0.6.1|
|''Author''|Jon Robson|
|''Status''|beta|
!Usage
{{{<<groupBy tags>>}}}
mimics allTags macro
{{{<<groupBy server.bag>>}}}
groups by the server.bag field (this version contains TiddlySpace specific code for turning a bag into a space name)
{{{groupBy modified dateFormat:"YYYY"}}}
group tiddlers by year.
{{{<<groupBy tags exclude:excludeLists exclude:systemConfig>>}}}
group tiddlers by tag but exclude the tags with values excludeLists and systemConfig
Within that group you can also exclude things by filter
{{{groupBy modifier filter:[tag[film]]}}}
will group tiddlers tagged with film by modifier.
***/
//{{{
(function($) {
var taglocale = config.views.wikified.tag;
var macro = config.macros.groupBy = {
locale: {
tooltip: "all tiddlers in group %0",
noTiddlers: "no tiddlers",
openAllText: taglocale.openAllText,
openAllTooltip: taglocale.openAllTooltip,
openTiddler: "open tiddler with title %0"
},
morpher: {
// TODO: note currently the following 2 morphers are TiddlySpace specific and probably should be in separate plugin
"server.workspace": function(value, options) {
return macro.morpher["server.bag"](value.replace("bags/", "").replace("recipes/", ""));
},
"server.bag": function(value, options) {
if(typeof(value) !== "string") {
return false;
} else if(value.indexOf("_public") === -1 && value.indexOf("_private") === -1) {
value = "*%0".format(value); // add star for non-space bags.
}
return value.replace("_public", "").replace("_private", "");
},
created: function(value, options) {
return value.formatString(options.dateFormat || "DD MMM YYYY");
},
modified: function(value, options) {
return macro.morpher.created(value, options);
}
},
handler: function(place, macroName, params, wikifier, paramString) {
var field = params[0] || "server.workspace";
var dateFormat = params[1] || "DD MMM YYYY";
var container = $("<div />").attr("macroName", macroName).addClass("groupBy").
attr("refresh", "macro").attr("fieldName", field).
attr("paramString", paramString).
attr("dateFormat", dateFormat).appendTo(place)[0];
macro.refresh(container);
},
isTypeArray: function(value) {
var valueType = typeof value;
if(valueType === "object" && typeof value.length === "number" &&
!(value.propertyIsEnumerable("length")) &&
typeof value.splice === "function") { //is Array
return true;
} else {
return false;
}
},
_onClickGroup: function(ev, options) {
var i, target = ev.target, locale = macro.locale;
var tiddlers = $(target).closest(".templateContainer").data("tiddlers");
var popup = $(Popup.create(target)).addClass("taggedTiddlerList")[0];
var value = $(target).attr("value");
var openAll = createTiddlyButton($("<li />").appendTo(popup)[0],
locale.openAllText.format(value), locale.openAllTooltip);
$(openAll).click(function(ev) {
story.displayTiddlers(ev.target, tiddlers);
return false;
});
var listBreak = $("<li />").addClass("listBreak").html("<div />").appendTo(popup);
for(i = 0; i < tiddlers.length; i++) {
var item = $("<li />").appendTo(popup)[0];
var template = store.getTiddlerText(options.template) || macro.template;
wikify(template, item, null, tiddlers[i]);
}
listBreak.clone().appendTo(popup);
$(createTiddlyLink($("<li />").appendTo(popup)[0], value, false)).
text(locale.openTiddler.format(value));
Popup.show();
ev.stopPropagation();
return false;
},
_refresh: function(container, tiddlers, options) {
var totalGroups = 0, locale = macro.locale, i, j;
var excludeValues = options.exclude;
var values = {}, value_ids = [];
var field = options.field;
var morpher = macro.morpher[field] || function(value) {
return value;
};
for(i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var value = tiddler[field] || tiddler.fields[field];
value = macro.isTypeArray(value) ? value : [ value ];
for(j = 0; j < value.length; j++) {
var v = morpher(value[j], options);
if(v && excludeValues.indexOf(v) === -1) {
totalGroups += 1;
if(!values[v]) {
values[v] = [];
}
values[v].push(tiddler);
value_ids.pushUnique(v);
}
}
}
var ul = $("<ul />").appendTo(container)[0];
if(totalGroups === 0) {
$("<li />").addClass("listTitle").text(locale.noTiddlers);
}
value_ids = value_ids.sort();
var groupTemplate = store.getTiddlerText(options.groupTemplate);
var onClick = function(ev) {
macro._onClickGroup(ev, options);
};
for(i = 0; i < value_ids.length; i++) {
var title = value_ids[i];
var info = getTiddlyLinkInfo(title);
tiddlers = values[title];
var btn = createTiddlyButton($("<li />").appendTo(ul)[0],
"%0 (%1)".format(title, tiddlers.length), locale.tooltip.format(title), null, info.classes);
if(groupTemplate) {
$(btn).empty();
wikify(groupTemplate, btn, null, tiddlers[0]);
}
$(btn).click(onClick).attr("value", title).attr("refresh", "link").attr("tiddlyLink", title);
$(btn).addClass("templateContainer").data("tiddlers", tiddlers);
}
},
refresh: function(container) {
container = $(container).empty();
var paramString = container.attr("paramString");
var args = paramString.parseParams("name", null, true, false, true)[0];
var options = { field: container.attr("fieldName"), dateFormat: container.attr("dateFormat"), exclude: args.exclude || [],
template: args.template ? args.template[0] : false, groupTemplate: args.groupTemplate ? args.groupTemplate[0] : "" };
var tiddlers = args.filter ? store.filterTiddlers(args.filter[0]) : store.getTiddlers("title");
macro._refresh(container, tiddlers, options);
},
template: "<<view title link>>"
};
}(jQuery));
//}}}
/***
|''Name''|TiddlySpaceFilters|
|''Description''|provide TiddlySpace-specific filter extensions|
|''Author''|Jon Robson|
|''Version''|0.6.1|
|''Status''|@@beta@@|
|''CoreVersion''|2.6.2|
|''Requires''|TiddlySpaceConfig|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
{{{
<<tsList Private>>
<<tsList Public>>
<<tsList Draft>>
}}}
!Code
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace;
var privateBag = tiddlyspace.getCurrentBag("private");
var publicBag = tiddlyspace.getCurrentBag("public");
config.filterHelpers = {
is: {
"private": function(tiddler) {
var bag = tiddler.fields["server.bag"];
return bag == privateBag;
},
"public": function(tiddler) {
var bag = tiddler.fields["server.bag"];
return bag == publicBag;
},
draft: function(tiddler) {
var fields = tiddler.fields;
var bag = fields["server.bag"];
return (privateBag == bag && fields["publish.name"]) ? true : false;
},
local: function(tiddler) {
return config.filterHelpers.is["public"](tiddler) ||
config.filterHelpers.is["private"](tiddler);
},
unsynced: function(tiddler) {
return tiddler ? tiddler.isTouched() : false;
}
}
};
config.filters.is = function(results, match) {
var candidates = store.getTiddlers("title");
var type = match[3];
for (var i = 0; i < candidates.length; i++) {
var tiddler = candidates[i];
var helper = config.filterHelpers.is[type];
if(helper && helper(tiddler)) {
results.pushUnique(tiddler);
}
}
return results;
};
})(jQuery);
//}}}
/***
|''Name''|DiffFormatter|
|''Description''|highlighting of text comparisons|
|''Author''|FND|
|''Version''|0.9.0|
|''Status''|beta|
|''Source''|http://svn.tiddlywiki.org/Trunk/contributors/FND/formatters/DiffFormatter.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/contributors/FND/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Keywords''|formatting|
!Description
Highlights changes in a unified [[diff|http://en.wikipedia.org/wiki/Diff#Unified_format]].
!Notes
Based on Martin Budden's [[DiffFormatterPlugin|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/DiffFormatterPlugin.js]].
!Usage
The formatter is applied to blocks wrapped in <html><code>{{{diff{..}}}</code></html> within tiddlers tagged with "diff".
!Revision History
!!v0.9 (2010-04-07)
* initial release; fork of DiffFormatterPlugin
!StyleSheet
.diff { white-space: pre; font-family: monospace; }
.diff ins, .diff del { display: block; text-decoration: none; }
.diff ins { background-color: #dfd; }
.diff del { background-color: #fdd; }
.diff .highlight { background-color: [[ColorPalette::SecondaryPale]]; }
!Code
***/
//{{{
(function() {
config.shadowTiddlers.StyleSheetDiffFormatter = store.getTiddlerText(tiddler.title + "##StyleSheet");
store.addNotification("StyleSheetDiffFormatter", refreshStyles);
var formatters = [{
name: "diffWrapper",
match: "^\\{\\{diff\\{\n", // XXX: suboptimal
termRegExp: /(.*\}\}\})$/mg,
handler: function(w) {
var el = createTiddlyElement(w.output, "div", null, "diff");
w.subWikifyTerm(el, this.termRegExp);
}
}, {
name: "diffRange",
match: "^(?:@@|[+\\-]{3}) ",
lookaheadRegExp: /^(?:@@|[+\-]{3}) .*\n/mg,
handler: function(w) {
createTiddlyElement(w.output, "div", null, "highlight").
innerHTML = "…";
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
}, {
name: "diffAdded",
match: "^\\+",
termRegExp: /(\n)/mg,
handler: function(w) {
var el = createTiddlyElement(w.output, "ins", null, "added");
w.subWikifyTerm(el, this.termRegExp);
}
}, {
name: "diffRemoved",
match: "^-",
termRegExp: /(\n)/mg,
handler: function(w) {
var el = createTiddlyElement(w.output, "del", null, "removed");
w.subWikifyTerm(el, this.termRegExp);
}
}
];
config.parsers.diffFormatter = new Formatter(formatters);
config.parsers.diffFormatter.format = "diff";
config.parsers.diffFormatter.formatTag = "diff";
})();
//}}}
This tiddler has been deleted.
[[Privateer|/Privateer]] operates by making requests against an HTTP API on the TiddlySpace server. That API can be accessed with your own tools if you like. The API is quite simple:
!!{{{GET /_}}}
Get a JSON listing of all mappings belonging to the current user formed as a dictionary mapping the external public URI to the internal private URI. The URIs are fully qualified with hostname and may involve multiple hostnames if there are mappings from multiple spaces.
!!{{{GET /_/<mapping id>}}}
Get the private resource mapped by mapping id. Internally the current user is identified as the user that created the mapping, not the user actually making the request.
!!{{{DELETE /_/<mapping id>}}}
If the current user matches the user that created the mapping, delete, irrevocably, the mapping.
!!{{{POST /_}}}
If the current user is not {{{GUEST}}} accept posted data to create a mapping. If the mapping is successful the response is {{{201}}} and the {{{Location}}} header contains the mapping URI. The posted content is either:
* a {{{JSON}}} dictionary with a key named {{{uri}}} with a value of the URI to be mapped to.
* a url-encoded parameter string with a parameter named {{{uri}}} with a value of the URI to be mapped to.
!!!The Trigger
I found [[Dictionary Lookups in JavaScript|http://ejohn.org/blog/dictionary-lookups-in-javascript/]] and its followups [[JavaScript Trie Performance Analysis|http://ejohn.org/blog/javascript-trie-performance-analysis/]], [[Revised JavaScript Dictionary Search|http://ejohn.org/blog/revised-javascript-dictionary-search/]] from John Resig, which are quite interesting articles.
I want to point your interest to the comments section of the first article [1]. It seems to be in the genes of programmers, to optimize everything. Especially the speed in general. But as everything else, there are allways two sides of the medal. Which is proven by John's second article. ... And still the "optimisation" goes on. see the comments ..
!!!Some Info
* An article from Steve Hanov triggered my interest. [[Succinct Data Structures: Cramming 80,000 words into a Javascript file|http://stevehanov.ca/blog/index.php?id=120]]
* https://github.com/mckoss/lookups looks promising too.
** Even more promising at the second look. ...
!!!The Idea
It seems to be a possibility for a TiddlySpace "keyword" search, that can be "easily" performed ''client and server side''.
* server side: eg usa a [[inverted indx|http://en.wikipedia.org/wiki/Full_text_index#Inverted_indices]] of the
* client side: tiddler key words
* if the user types in the first word to be found a skinny json list will be sent to the client (may be ranked first 50)
* the client searches the keyword list for the second and third keywords and make it smaller
** client sends second and third keword to server
** sverver sends a update list ...
A directory, eg:
{{{
apple orange alphapha
lamp hello jello quiz
}}}
results in an encoded/compressed directory like:
//{{{
{
"nodeCount": 37,
"directory": "BMIg",
"trie": "v2qqqqqqqpIUn4A5JZyBZ4ggCKh55ZZgBA5ZZd5vIEl1wx8g8A"
}
//}}}
{{{Encoded 44 bytes to 115 bytes.}}}
Which results in a smaller size trie for bigger sets of directories, that can be directly used without decompression.
>"We only handle the letters "a" to "z" in lower case. That way, we can encode each letter in 5 bits.
You can <<slider chkIframe hanovsolutionsIframe "Test it ..." "Test it ...">>
Since the [[source code|http://www.hanovsolutions.com/trie/Bits.js]] is public domain, it should be easy to implement.
!!!Keyword - Limited Full Text Search
Since I thought the encoded data will be stored as custom fields, it is a lot of redundancy, to have the "full text" there. So I would exclude words less than 3 characters, articles, conjunctions ... and may be some TW macro names.
Or manually limit it to keywords, provided by an "intelligent" algorithm (to be found :).
!!!Algorithm to get directory
* Hyphenation, could help to get better keywords
** Javascript that implements client-side hyphenation of HTML-Documents http://code.google.com/p/hyphenator/wiki/en_PublicAPI
* Use Plugins, Keyword slice
----
I made several tests and found out, that it doesn't compress well, if the dictionary set is "small" eg: containing the text of this article.
{{{
a algorithm analyse article
better
case client comment compress conjunction cramming custom
data decompression dictionary directory domain
encode exclude
field file first followup full
genes
handle hanov hyphenation
idea implement intelligent interest
javascript john
keyword
letter limit lookup lower
macro manually
name nodecount
optimize
performance programmer public
redundancy resig result
search section server side size slice smaller speed steve structure succinct
tiddlyspace trie trigger tw
words
z
}}}
results in
{{{
{
"nodeCount": 374,
"directory": "BwMxIFoax-I4niuL8zjdOw-0JRdJEyT9TFaWdcw",
"trie": "v__-6-9ut2utdf3SqrVWq6qqqq2qq3arVKqrVVVVVWqqqqqqrVVVVaqlVSqqUqlpVVKqqqKqpVVVVVUSVVSKqpVIqlRVKilVRVSJVUKqlVSqoqSVKklUlSUqVKRIJ_ACEGIKMOQSUWYaceikmtyWaiIAWcioAIQcauQcoIAwGYaAcIIQcAAceIioIIQWYemoQjscMAmmkQYaAkmEEiYEEIWiWWaaeIemqOwmYcsEaYGmicCGkAEiGyQAIIiEGQicWQnIIYeSYnAcmIAcWXIkXWIGcPAWIBasmQUIipIIQKMWoQoimrJIEWIqoEHIMGiwEIaIioYcYQEQGpHmdkXqIIWikcJmpjcAEYciQbMWEQJIXHIEQWNkQkXjmaIaRYecnbIGtIaYWIEjjeWcQiBEHnOdiImawInJJmkEaiadIoAIQkjGWoyYYBbioEliPknMIAjemaNmRwbIAYajmfYQkjwRmIfmaIFIAclwcbmFjwFaRbnJIda"
}
}}}
source: 526 - output: 600
* Which will probably allways be the case, since the dictionary doesn't have common prefixes.
* So it would need to make the dictionary better and have words + there derivations. Which will make the search results much better.
eg: if the dictionary contains sigular and plural ...
{{{
a algorithm algorithms analyse analyses article articles
better
case cases client clients comment comments compress conjunction conjunctions cramming custom
data decompression dictionary dictionaries directory directories domain domains
encode encoded exclude excludes
field fields file files first followup followups full
genes gene
handle hanov hyphenation
idea ideas implement implementation intelligent interest interests
javascript john
keyword keywords
letter limit limits lookup lookups lower
macro macros manually
name names nodecount
optimize
performance programmer programmers public
redundancy resig result results
search section sections server servers side size slice slices small smaller speed steve structure structures succinct
tiddlyspace trie trigger tw
word words
z
}}}
result
{{{
{
"nodeCount": 411,
"directory": "BwMxIFoax-I4niuL8zzfO4_UMRlJ02UNUVgWteWHZU",
"trie": "v__-6-9ut2utdf3SqrVWq6qqqq2qq3arVKqrVVVVVWqqqqqqrVVVVaqqqpVVVKqtKqqqqqoqqlVSqqqqJJVVSlVSqoqlSqlVSVVEqpSlVVKqoqqpVUipBKyqolSVWipKqVKpRVECSfwAhBiCjDkElFmGnHopJrclmoiAFnIqACEHGrkHKCAMBmGgHCCEHAAHHiIqCCEFmHpqEI7HDAJppEGGgJJhBImBBCFollmmniHpqjsJmHLBGmBponAhpABIhskACCIhBkInFkJyCGHkmJwHJiAHFlyJF1yBnDwFiAWrJkFCIqSCECjFqEKIpqySBFiKqBByDRosBCZGiIqGHGEBEBqR5ZnZF6iZCFopHCZqY3AZBGHIkGzFhECSVxyBEFjZEJF45miGkWHnJ2yB5LSGmFiBI45X5FnEIgRB5znY5CJmsCJySZZpBGomnZRyKACEJIx5FqMmGAZW5YqBJYj5ZZZJzCAI5XpmjZkZcGyAGG5I5n2EJIkcZEZiZH5miBSAZHJEcCHAG5hY8ZBWkCZWp5yZSZHZEWnWg"
}
}}}
source 804 - result 653
* The disadvantage is, that it needs a big dictionary to find/create the derevations for the tiddler dictionary. :(
* There will be better algorithms to face this problem.
----
* https://github.com/mckoss/lookups looks promising too.
* For me TiddlySpace is the serverside, that spits out TWs.
** Combined using the include mechanism.
** Using the include mechanism is easier than manually create recipes/bags .. with hoster
** Using it introduces limitations, that had to be made to make it more secure.
*** Using it lets you try to work around them.
** Using it creates a "subdomain" which is nice / personal / ... I like that :)
** Using it creates links, that are more beautiful than {{{http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki}}} or {{{http://hoster.peermore.com/bags/TeamPubMp/tiddlers/Create New Tiddler with a transcluded script}}}
** Using it lets you create new experiments within 2 hours (simplicity)
*** Using it makes you crazy, because creating the CSS and a deploy mechanism, adds several hours instead of minutes.
* TiddlyWeb is the serverside, that spits out tiddlers.
** The power is with it.
** I love it, but that's it :(
/***
|''Name''|NewTaggedCommand|
|''Description''|Creates a new tiddler, and tags it with it's parents title!|
|''Authors''|PMario|
|''Version''|0.1.1|
|''Date''|2011-07-20|
|''Status''|@@beta@@|
|''Source''|http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki#NewTaggedCommand|
|''License''|BSD|
|''CoreVersion''|2.5|
|''Keywords''|toolbar command add new tagged tiddler|
!!!Description
<<<
To use this new toolbar command you have to add {{{newTagged}}} to ToolbarCommands tiddler
eg:
{{{
|~ViewToolbar| +editTiddler newTagged ...
}}}
<<<
!!!Change the button text
<<<
If you want to change the buttons text from "newTagged" to eg "+", you need to create at tiddler [[zzConfig]] and tag it "systemConfig" and insert the following line.
//{{{
config.commands.newTagged.text = "+";
//}}}
<<<
!!!Code
***/
//{{{
config.commands.newTagged = {
text: "newTagged",
tooltip: "Create a new tiddler, and tag it!",
isEnabled: function(tiddler) {
return !readOnly;
}
};
config.commands.newTagged.handler = function(event,src,title)
{
var newTitle = config.macros.newTiddler.title;
story.displayTiddler(null, newTitle);
config.commands.editTiddler.handler.call(this,event,src,newTitle);
story.setTiddlerTag(newTitle, title, +1);
return false;
};
//}}}
Work in progress. May be moved to its own destination space.
! How To Create ~TiddlyWiki Plugins
I did create some videos at my [[Youtube Cahnnel|https://www.youtube.com/user/pmariojo]], that show how to create a TW plugin, using ~TiddlySpace.
''The videos should be viewed in the following order.''
!! Playlist: "TW plugins and debugging"
Playlist "TW plugins and debugging":
https://www.youtube.com/watch?v=J5tq5xv0FHU&list=PL19F78517CB1EDC08&feature=view_all
!!! How to Setup a ~TiddlyWiki Development Space
* ~HowTo: Setup a ~TiddlyWiki development space
** http://www.youtube.com/watch?v=J5tq5xv0FHU
!!! How to Debug a Plugin
* ~HowTo: Debug a ~TiddlyWiki plugin
** http://www.youtube.com/watch?v=h3NjTLQXWRc
!!! How ~TiddlyWiki Plugins Work
* Info: How ~TidddlyWiki plugins work
** http://www.youtube.com/watch?v=XEXIIs16yto
!!! Why Inline Scripts should be Plugins
* Info: Why Inline Scripts should be Plugins
** http://www.youtube.com/watch?v=Hc6IPovgvbo
!!! From Inline Script to Plugin
* ~HowTo: convert a ~TiddlyWiki inline script into a plugin
** http://www.youtube.com/watch?v=6u7-GdAsukw
!! Related Informations
* tiddlywiki.org - Best Practices - http://tiddlywiki.org/#%5b%5bBest%20Practices%5d%5d
* Mozilla Development Network - Closures: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
* Development Environment: http://dev-env.tiddlyspace.com/
* ~NEUI-EM Theme: http://neui-em.tiddlyspace.com/
* ~CodeMirror Editor: http://codemirror-plugins.tiddlyspace.com/
* ~POSTagger Video: http://postagger-video.tiddlyspace.com/
* ~POSTagger Experimental: http://postagger.tiddlyspace.com/
* ~POSTagger plugins: http://postagger-plugins.tiddlyspace.com/
! Wallpaper Creator for Ubuntu Unity
Some bash scripts that can create an Ubuntu Desktop Wallpaper, that contains some of your favorite picturs and a live calendar.
* You like to have some of your favorite pictures, to be part of the desktop but they shouldn't use the whole space.
* You like to have a calendar right on the desktop.
* You like "abstract" desktop backgrounds.
Interested? Have a look at @wpc space.
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{
window.hideWhenLastTest = false;
window.removeElementWhen = function(test,place) {
window.hideWhenLastTest = test;
if (test) {
jQuery(place).empty()
place.parentNode.removeChild(place);
}
};
merge(config.macros,{
hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( eval(paramString), place);
}},
showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !eval(paramString), place);
}},
hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAny(params), place);
}},
showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAny(params), place);
}},
hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.tags.containsAll(params), place);
}},
showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !tiddler.tags.containsAll(params), place);
}},
hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
}},
showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
}},
hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title == params[0], place);
}},
showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( tiddler.title != params[0], place);
}},
'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
removeElementWhen( !window.hideWhenLastTest, place);
}}
});
//}}}
/***
|''Name''|TiddlyFileImporter|
|''Version''|0.3.8|
|''Author''|Ben Gillies|
|''Type''|plugin|
|''Description''|Upload a TiddlyWiki file to TiddlyWeb, and import the tiddlers.|
!Usage
Upload a TiddlyWiki file to TiddlyWeb, and import the tiddlers.
!Requires
tiddlyweb
tiddlywebplugins.reflector
!Code
***/
//{{{
(function($){
if(!version.extensions.TiddlyFileImporter)
{ //# ensure that the plugin is only installed once
version.extensions.TiddlyFileImporter = { installed: true };
}
config.macros.fileImport = {
reflectorURI: '/reflector?csrf_token=%0',
incorrectTypeError: 'Incorrect File Type. You must upload a TiddlyWiki',
uploadLabel: 'Upload',
uploadLabelPrompt: 'Import tiddlers from this TiddlyWiki',
step1FileText: 'File:',
step1PostText: 'In the next screen you will select the tiddlers to import.',
step1Title: 'Step 1: Pick a TiddlyWiki to import',
step1TypeChooser: 'Import From:',
step3Html: ['<input type="hidden" name="markList" />',
'<input type="hidden" checked="true" name="chkSync" />',
'<input type="hidden" name="chkSave" />',
'<input type="hidden" name="txtSaveTiddler" />'].join(),
handler: function(place, macroName, params, wikifier, paramString) {
var wizard = new Wizard();
wizard.createWizard(place, 'Import a TiddlyWiki');
this.restart(wizard);
},
restart: function(wizard) {
var me = config.macros.fileImport;
wizard.addStep(me.step1Title, ['<input type="hidden" ',
'name="markList" />'].join(""));
var markList = wizard.getElement('markList');
var uploadWrapper = document.createElement('div');
markList.parentNode.insertBefore(uploadWrapper, markList);
uploadWrapper.setAttribute('refresh', 'macro');
uploadWrapper.getAttribute('macroName', 'fileImport');
var iframeName = 'reflectorImporter' + Math.random().toString();
me.createForm(uploadWrapper, wizard, iframeName);
$(uploadWrapper).append('<p>' + me.step1PostText + '</p>');
wizard.setValue('serverType', 'tiddlyweb');
wizard.setValue('adaptor', new config.adaptors.file());
wizard.setValue('host', config.defaultCustomFields['server.host']);
wizard.setValue('context', {});
var iframe = $(['<iframe name="' + iframeName + '" ',
'style="display: none" />'].join("")).appendTo(uploadWrapper);
var onSubmit = function(ev) {
var uploadType = $('select[name=uploadtype]', wizard.formElem).val();
if (uploadType == "file") {
// set an onload ready to hijack the form
me.setOnLoad(uploadWrapper, wizard, iframe[0]);
wizard.importType = 'file';
wizard.formElem.submit();
} else {
var csrf_token = config.extensions.tiddlyspace.getCSRFToken();
$.ajax({
url: "%0/reflector?csrf_token=%1".format(
config.defaultCustomFields["server.host"], csrf_token),
type: "POST",
dataType: "text",
data: {
uri: $("input", ".importFrom", wizard.formElem).val()
},
success: function(data, txtStatus, xhr) {
wizard.POSTResponse = data;
me.importTiddlers(uploadWrapper, wizard);
},
error: function(xhr, txtStatus, error) {
displayMessage(["There was an error fetching the ",
'url: ', txtStatus].join(""));
me.restart(wizard);
}
});
return false;
}
};
wizard.setButtons([{
caption: me.uploadLabel,
tooltip: me.uploadLabelPrompt,
onClick: onSubmit
}]);
$(wizard.formElem).submit(function(ev) {
onSubmit(ev);
ev.preventDefault();
});
},
createForm: function(place, wizard, iframeName) {
var form = wizard.formElem;
var me = config.macros.fileImport;
form.action = me.reflectorURI.format(
config.extensions.tiddlyspace.getCSRFToken());
form.enctype = 'multipart/form-data';
form.encoding = 'multipart/form-data';
form.method = 'POST';
form.target = iframeName;
onSelectChange = function(e) {
var changeTo = $(this).val();
if (changeTo == "file") {
$(".importFrom").html('%0 <input type="file" name="file" />'.
format(me.step1FileText));
} else {
$(".importFrom").html('URL: <input type="text" name="uri" />'
+ ' Do you want <a target="_blank" href="http://faq.tiddlyspace.com/How%20do%20I%20include%2Fexclude%20spaces%3F">inclusion</a> instead?');
}
};
$(place).append('<span>%0</span>'.format(me.step1TypeChooser)).
append($(['<select name="uploadtype"><option value="file" selected="selected">file',
'<option value="uri">url</select>'].join("")).change(onSelectChange)).
append('<div class="importFrom">%0<input type="file" name="file" /></div>'.
format(me.step1FileText));
},
setOnLoad: function(place, wizard, iframe) {
var me = config.macros.fileImport;
var loadHandler = function() {
me.importTiddlers.apply(this, [place, wizard, iframe]);
};
iframe.onload = loadHandler;
completeReadyStateChanges = 0;
iframe.onreadystatechange = function() {
if (++(completeReadyStateChanges) == 5) {
loadHandler();
}
};
},
importTiddlers: function(place, wizard, iframe) {
var tmpStore = new TiddlyWiki();
var POSTedWiki = "";
if (wizard.importType == "file") {
try {
POSTedWiki= iframe.contentWindow
.document.documentElement.innerHTML;
} catch(e) {
displayMessage(config.macros.fileImport.incorrectTypeError);
config.macros.fileImport.restart(wizard);
return;
}
// now we are done, so remove the iframe
$(iframe).remove();
} else {
POSTedWiki = wizard.POSTResponse;
}
tmpStore.importTiddlyWiki(POSTedWiki);
var newTiddlers = tmpStore.getTiddlers();
var workspace = config.defaultCustomFields['server.workspace'];
var context = {
status: true,
statusText: 'OK',
httpStatus: 200,
adaptor: wizard.getValue('adaptor'),
tiddlers: newTiddlers
};
context.adaptor.store = tmpStore;
wizard.setValue('context', context);
wizard.setValue('workspace', workspace);
wizard.setValue('inFileImport', true);
config.macros.importTiddlers.onGetTiddlerList(context, wizard);
}
};
var _onGetTiddler = config.macros.importTiddlers.onGetTiddler;
config.macros.importTiddlers.onGetTiddler = function(context, wizard) {
if (wizard.getValue('inFileImport')) {
var me = config.macros.importTiddlers;
if(!context.status)
displayMessage("Error in importTiddlers.onGetTiddler: " + context.statusText);
var tiddler = context.tiddler;
var fields = tiddler.fields;
merge(fields, config.defaultCustomFields);
fields["server.workspace"] = wizard.getValue('workspace');
delete fields['server.permissions'];
delete fields['server.bag'];
fields['server.page.revision'] = 'false';
delete fields['server.recipe'];
fields.changecount = 1;
store.suspendNotifications();
store.saveTiddler(tiddler.title, tiddler.title, tiddler.text,
tiddler.modifier, tiddler.modified, tiddler.tags, tiddler.fields,
false, tiddler.created);
store.resumeNotifications();
var remainingImports = wizard.getValue("remainingImports")-1;
wizard.setValue("remainingImports",remainingImports);
if(remainingImports === 0) {
if(context.isSynchronous) {
store.notifyAll();
refreshDisplay();
}
wizard.setButtons([
{caption: me.doneLabel, tooltip: me.donePrompt, onClick: me.onClose}
],me.statusDoneImport);
autoSaveChanges();
}
} else {
_onGetTiddler.apply(this, arguments);
}
};
var _onCancel = config.macros.importTiddlers.onCancel;
config.macros.importTiddlers.onCancel = function(e)
{
var wizard = new Wizard(this);
if (!wizard.getValue('inFileImport')) {
return _onCancel.apply(this, arguments);
}
var place = wizard.clear();
config.macros.fileImport.restart(wizard);
return false;
};
var _step3Html = config.macros.importTiddlers.step3Html;
var _onGetTiddlerList = config.macros.importTiddlers.onGetTiddlerList;
config.macros.importTiddlers.onGetTiddlerList = function(context, wizard) {
var fileImport = config.macros.fileImport;
var importTiddlers = config.macros.importTiddlers;
if (wizard.getValue('inFileImport')) {
importTiddlers.step3Html = fileImport.step3Html;
} else {
importTiddlers.step3Html = _step3Html;
}
_onGetTiddlerList.apply(this, arguments);
};
})(jQuery);
//}}}
/*{{{*/
body {
font-size: 1em;
font-family: helvetica, arial, sans-serif;
background-color: #fff;
color: [[ColorPalette::Foreground]];
}
body ul { margin: 0; }
#popup {
background-color: [[ColorPalette::TertiaryPale]];
}
#popup.confirmationPopup, .followList {
font-size: 0.8em;
padding: 1em;
border: solid 1px [[ColorPalette::SecondaryMid]];
background-color: [[ColorPalette::SecondaryPale]];
}
.followList .listTitle {
text-decoration: underline;
}
#popup .followTiddlersList a {
display: inline;
padding: 0;
}
#popup li a {
color: [[ColorPalette::PrimaryMid]];
font-weight: bold;
}
#popup li a:hover {
color: [[ColorPalette::PrimaryPale]];
background: [[ColorPalette::PrimaryMid]];
}
#popup li.listTitle {
border-bottom: 1px solid #000;
font-weight: bold;
margin-bottom: 10px;
}
#popup.followList {
margin-left: 50px;
margin-top: -30px;
}
.followTiddlersList .label {
display: block;
left: 10px;
top: 0px;
line-height: 16px;
position: relative;
}
#popup .followTiddlersList .siteIcon{
height: auto;
}
#popup .followTiddlersList li{
clear: both;
display: block;
height: 48px;
margin-bottom: 8px;
position: relative;
}
#popup .followTiddlersList a{
display: inline;
}
#displayArea {
margin: 0;
top: 0px;
left: 0px;
width: 100%;
position: relative;
}
.revisionCloak {
position: absolute;
position: fixed !important;
height: 100%;
width: 100%;
top: 0;
left: 0;
border: 0;
margin: 0;
padding: 0;
opacity: 0.5;
filter: alpha(opacity=50);
background-color: #000;
}
/* *** Header *** */
.header {
position: relative;
background-color: [[ColorPalette::PrimaryMid]];
_width: 100%; /* ie 6 demands */
}
.headerForeground {
background-color: [[ColorPalette::PrimaryMid]];
float: left;
margin: 24px 16px 0px 72px;
padding: 0;
position: relative;
top: 0;
_width: 70%; /*ie6: needed for the background to actually be transparent*/
_background-color: transparent; /*ie6: needed to show the search box*/
}
.clearFloat {
clear: both;
}
#contentWrapper {
position: relative;
padding-top: 1px;
top: -1px;
}
#tiddlerDisplay {
_position: relative; /* ie 6*/
}
.siteTitle {
clear: both;
display: block;
font-size: 32px;
font-weight: bold;
line-height: 32px;
}
.siteSubtitle {
display: block;
font-size: 14px;
height: 16px;
margin-bottom: 8px;
}
#sidebarSearch {
padding: 0;
position: absolute;
right: 80px;
top: 8px;
width: 176px;
}
#sidebarSearch .txtOptionInput {
width: 100%;
margin-top: 5px;
_color: #bbb; /* ie6 danger */
}
#sidebarSearch .txtOptionInput:focus {
color: #000;
}
#sidebarSearch .searchButton {
display: none;
}
/* *** Menu Bar *** */
#mainMenu {
position: static;
text-align: left;
margin-left: 72px;
float: left;
width: auto;
padding: 0;
font-size: 1em;
line-height: normal;
}
#mainMenu a {
color: #fff;
padding: 8px;
font-size: 0.9em;
margin-right: 16px;
}
#mainMenu a:hover {
background-color: [[ColorPalette::PrimaryMid]];
color: [[ColorPalette::Background]]
}
#sidebarOptions {
margin-right: 72px;
float: right;
font-size: 1.1em;
line-height: 1.6em;
min-height: 1em;
padding-top: 0;
}
#sidebarOptions a {
margin-right: 8px;
}
.confirmationPopup .button,
#sidebarOptions .button {
cursor: pointer;
line-height: 1.4em;
text-align: center;
margin-right: 8px;
margin-left:-2px;
}
.confirmationPopup .button {
font-size: 0.9em;
padding: 2px;
}
#sidebarOptions .button {
font-size: 0.7em;
float: left;
width: 80px;
padding: 0px;
color: #fff;
}
.confirmationPopup a.button,
#sidebarOptions a {
border: none;
margin: 0 0.2em;
padding: 0.6em 0.25em;
display: inline;
color: #666;
}
.confirmationPopup a.button:hover,
#sidebarOptions a:hover {
color: #000;
}
.confirmationPopup a.button:active,
#sidebarOptions a:active {
border: solid 1px [[ColorPalette::PrimaryMid]];
background-color: #fff;
background: -webkit-gradient( linear, left bottom, left top, color-stop(0.1,rgb(200,200,200)), color-stop(1, rgb(100,100,100)));
background: -moz-linear-gradient(center bottom , rgb(200,200,200) 10%,rgb(100,100,100) 100%) repeat scroll 0 0 transparent;
}
/* *** Sidebar *** */
#sidebar .wizard table {
margin: 0px;
}
.tabContents .listTitle:first-child {
margin-top: 0px;
}
#menuBar {
background: [[ColorPalette::PrimaryLight]];
left: 0;
right: 0;
position: relative;
margin: 0;
padding: 0.5em 0 0.5em 0;
min-height: 1em;
overflow: hidden;
_width: 100%; /* for ie 6 */
}
#sidebarOptions a.button:hover {
color: [[ColorPalette::PrimaryPale]];
background: [[ColorPalette::PrimaryMid]];
}
#tiddlerDisplay, #searchResults {
margin: 16px 448px 0 72px;
}
#sidebarTabs {
position: absolute;
right: 72px;
width: 352px;
top: 0;
}
#sidebarTabs .tabsetWrapper .tabset {
width: 87px;
border-top: 1px solid [[ColorPalette::PrimaryPale]];
border-left: 1px solid [[ColorPalette::PrimaryPale]];
border-bottom: 1px solid [[ColorPalette::PrimaryPale]];
height: auto;
float: left;
word-wrap: break-word;
top: 0;
padding: 0;
}
#sidebarTabs .tabsetWrapper .tabContents {
background-color: [[ColorPalette::PrimaryPale]];
border: 3px solid [[ColorPalette::PrimaryMid]];
width: 242px;
_width: 238px;
left: -3px;
_left: -5px;
position: relative;
min-height: 34em;
padding: 8px;
font-size: 0.8em;
}
/* ---- Side style --- */
#sidebarTabs .tabsetWrapper .tabset .tab {
font-size: 0.9em;
padding: 0.7em 8px 0.5em;
color: #fff;
background: [[ColorPalette::PrimaryLight]];
border: none;
line-height: 16px;
position: relative;
display: block;
margin: 0;
}
#sidebarTabs .tabsetWrapper .tabset .tabSelected {
color: [[ColorPalette::PrimaryMid]];
background: [[ColorPalette::PrimaryPale]];
border-top: 3px solid [[ColorPalette::PrimaryMid]];
border-bottom: 3px solid [[ColorPalette::PrimaryMid]];
border-left: 3px solid [[ColorPalette::PrimaryMid]];
z-index: 10;
margin-top: -1px;
font-weight: bold;
}
#sidebarTabs .tabContents li {
border: none;
margin-left: 0;
word-wrap: break-word;
}
.tabContents .timeline {
background: [[ColorPalette::PrimaryPale]];
margin-bottom: 8px;
}
#sidebarTabs .timeline li.listTitle {
color: #132E43;
margin-left: 8px 0;
padding: 0.3em 0.11em;
font-size: 1em;
border-bottom: none;
}
#sidebarTabs .tabContents li a {
display: block;
text-align: left;
margin: 0 0 1px 0;
padding: 0.3em 1em;
background: [[ColorPalette::PrimaryPale]];
}
#sidebarTabs .tabsetWrapper .tabset a:hover,
#sidebarTabs .tabContents li a:hover {
color: [[ColorPalette::PrimaryPale]];
background: [[ColorPalette::PrimaryMid]];
}
/* Activity Stream */
#sidebarTabs .tabContents .activityStream .feedItem a {
display: inline-block;
padding: 0;
background: none;
}
/* ---- Tagging box --- */
.tagInfo {
border: 1px solid #cccccc;
padding: 10px 15px;
-moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 2px rgba(0,0,0,0.2);
color: [[ColorPalette::TertiaryMid]];
background: -moz-linear-gradient(100% 100% 90deg, #f4f4f4, #e5e5e5);
background: -webkit-gradient(linear, left top, right top, from(#e5e5e5), to(#f4f4f4));
margin-top: 1em;
font-size: 13px;
margin: 0 0 0 56px;
}
.tagInfo ul {
list-style: none;
padding-left: 2.2em;
}
.tagInfo ul li {
display: inline;
}
.tagInfo ul li.listTitle,
.tagInfo .tagging ul li.listTitle {
color: [[ColorPalette::PrimaryMid]];
font-size: 13px;
}
.tagInfo ul li a {
border: none;
}
.tagInfo .tagging ul li {
float: none;
display: inline-block;
}
.tagInfo .tagging {
padding: 0;
}
.viewRevision .toolbar {
right: 48px;
top: 8px;
}
.viewRevision .modifierIcon img,
.viewRevision .modifierIcon svg {
margin-right: 8px;
}
.viewRevision .toolbar svg {
width: 32px;
height: 32px;
}
/* --- IE hacks from lattice --- */
/* ie hacks */
* html #menuBar {
margin-bottom: 8px;
}
.toolbar .svgIconText {
*display: inline;
}
div.tiddler .toolbar a {
cursor: pointer;
float: left\9;
display: inline\9;
}
* html .toolbar {
right: 8px;
}
* html .followButton a {
margin-top: 0px;
margin-right: 8px;
}
* html #tiddlerDisplay {
margin-top: 0px;
}
/* for printing purposes */
@media print {
#mainMenu,
#sidebar,
#messageArea,
.toolbar,
.followPlaceHolder,
#backstageButton,
#backstageArea,
#sidebarTabs,
#sidebarSearch .txtOptionInput,
#sidebarOptions {
display: none !important;
}
#displayArea {
margin: 1em 1em 0em;
}
noscript {
display:none; /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
#tiddlerDisplay {
margin: 16px 16px;
}
}
@media all and (max-width: 960px){
#tiddlerDisplay,
#searchResults {
margin: 16px 366px 0 16px;
}
#mainMenu {
margin-left: 16px;
}
.headerForeground {
margin-left: 16px;
}
#sidebarSearch {
right: 16px;
}
#sidebarOptions {
margin-right: 16px;
}
#sidebarTabs {
right: 16px;
width: 326px;
}
#sidebarTabs .tabsetWrapper .tabset {
font-size: 0.9em;
width: 77px;
}
#sidebarTabs .tabsetWrapper .tabContents {
width: 226px;
_width: 222px;
}
#sidebarTabs .tabContents li a {
font-size: 0.9em;
}
}
/*}}}*/
[[StyleSheetTiddler]]
* As my main knowledge database (private)
* and presentation plattform. (private / public)
/***
|''Name''|TiddlySpaceConfig|
|''Version''|0.7.7|
|''Description''|TiddlySpace configuration|
|''Status''|stable|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceConfig.js|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlyWebConfig ServerSideSavingPlugin TiddlyFileImporter|
!Code
***/
//{{{
(function($) {
var tweb = config.extensions.tiddlyweb;
var recipe = config.defaultCustomFields["server.workspace"].split("recipes/")[1];
var currentSpace; // assigned later
var disabledTabs = [];
var coreBags = ["system", "tiddlyspace"];
var systemSpaces = ["plugins", "info", "images", "theme"];
systemSpaces = $.map(systemSpaces, function(item, i) {
return "system-%0_public".format(item);
});
// hijack search macro to add custom attributes for mobile devices
var _search = config.macros.search.handler;
config.macros.search.handler = function(place, macroName, params) {
_search.apply(this, arguments);
$(".searchField:input", place).
attr({ autocapitalize: "off", autocorrect: "off" });
};
// arg is either a container name or a tiddler object
// if fuzzy is truthy, space may be inferred from workspace (for new tiddlers)
// returns space object or false
var determineSpace = function(arg, fuzzy) {
if(typeof arg == "string") { // container name
var space = split(arg, "_", "r");
return ["public", "private"].contains(space.type) ? space : false;
} else if(arg) { // tiddler
var container = determineContainer(arg, fuzzy);
return container ? determineSpace(container.name, fuzzy) : false;
} else {
return false;
}
};
// if fuzzy is truthy, container may be inferred from workspace for new tiddlers
// returns container object or false
var determineContainer = function(tiddler, fuzzy) { // TODO: expose?
var bag = tiddler.fields["server.bag"];
var recipe = tiddler.fields["server.recipe"]; // XXX: unused/irrelevant/redundant!?
if(bag) {
return { type: "bag", name: bag };
} else if(recipe) {
return { type: "recipe", name: recipe };
} else if(fuzzy) { // new tiddler
var workspace = tiddler.fields["server.workspace"];
if(workspace) {
var container = split(workspace, "/", "l");
return ["bags", "recipes"].contains(container.type) ? container : false;
} else {
return false;
}
} else {
return false;
}
};
// hijack removeTiddlerCallback to restore tiddler from recipe cascade -- TODO: move into TiddlyWebWiki?
var sssp = config.extensions.ServerSideSavingPlugin;
var _removeTiddlerCallback = sssp.removeTiddlerCallback;
sssp.removeTiddlerCallback = function(context, userParams) {
var title = context.tiddler.title;
var recipe = context.tiddler.fields["server.recipe"];
_removeTiddlerCallback.apply(this, arguments);
if(recipe) {
context.workspace = "recipes/" + recipe;
var callback = function(context, userParams) {
if(context.status) {
var dirty = store.isDirty();
store.saveTiddler(context.tiddler).clearChangeCount();
store.setDirty(dirty);
} else {
store.notify(title, true);
}
};
context.adaptor.getTiddler(title, context, null, callback);
}
};
// splits a string once using delimiter
// mode "l" splits at the first, "r" at the last occurrence
// returns an object with members type and name
var split = function(str, sep, mode) {
mode = mode == "r" ? "pop" : "shift"; // TODO: use +/-1 instead of "l"/"r"?
var arr = str.split(sep);
var type = arr.length > 1 ? arr[mode]() : null;
return { type: type, name: arr.join(sep) };
};
var plugin = config.extensions.tiddlyspace = {
currentSpace: determineSpace(recipe),
coreBags: coreBags.concat(systemSpaces),
determineSpace: determineSpace,
isValidSpaceName: function(name) {
return name.match(/^[a-z][0-9a-z\-]*[0-9a-z]$/) ? true : false;
},
getCurrentBag: function(type) {
return "%0_%1".format(currentSpace, type);
},
getCurrentWorkspace: function(type) {
return "bags/" + this.getCurrentBag(type);
},
// returns the URL for a space's avatar (SiteIcon) based on a server_host
// object and an optional space name
// optional nocors argument prevents cross-domain URLs from being generated
getAvatar: function(host, space, nocors) {
if(space && typeof space != "string") { // backwards compatibility -- XXX: deprecated
space = space.name;
}
var subdomain = nocors ? currentSpace : space;
host = host ? this.getHost(host, subdomain) : "";
var bag = space ? "%0_public".format(space) : "tiddlyspace";
return "%0/bags/%1/tiddlers/SiteIcon".format(host, bag);
},
// returns the URL based on a server_host object (scheme, host, port) and an
// optional subdomain
getHost: function(host, subdomain) {
if(host === undefined) { // offline
tweb.status.server_host = {}; // prevents exceptions further down the stack -- XXX: hacky workaround, breaks encapsulation
return null;
}
subdomain = subdomain ? subdomain + "." : "";
var url = "%0://%1%2".format(host.scheme, subdomain, host.host);
var port = host.port;
if(port && !["80", "443"].contains(port)) {
url += ":" + port;
}
return url;
},
disableTab: function(tabTiddler) {
if(typeof(tabTiddler) == "string") {
disabledTabs.push(tabTiddler);
} else {
for(var i = 0; i < tabTiddler.length; i++) {
plugin.disableTab(tabTiddler[i]);
}
}
},
checkSyncStatus: function(tiddler) {
if(tiddler) {
var title = typeof(tiddler) === "string" ? tiddler : tiddler.title;
var el = story.getTiddler(title) || false;
if(el) {
refreshElements(el);
}
}
},
isDisabledTab: function(tabTitle) {
var match = new RegExp("(?:\\[\\[([^\\]]+)\\]\\])", "mg").exec(tabTitle);
var tabIdentifier = match ? match[1] : tabTitle;
return disabledTabs.contains(tabIdentifier);
},
getCSRFToken: window.getCSRFToken || null // this may not have been processed yet
};
currentSpace = plugin.currentSpace.name;
tweb.serverPrefix = tweb.host.split("/")[3] || ""; // XXX: assumes root handler
tweb.getStatus(function(status) {
var url = plugin.getHost(status.server_host);
tweb.status.server_host.url = url;
config.messages.tsVersion = status.version;
});
if(window.location.protocol == "file:") {
// enable AutoSave by default
config.options.chkAutoSave = config.options.chkAutoSave === undefined ?
true : config.options.chkAutoSave;
} else {
// set global read-only mode based on membership heuristics
var indicator = store.getTiddler("SiteTitle") || tiddler;
readOnly = !(recipe.split("_").pop() == "private" ||
tweb.hasPermission("write", indicator));
// replace TiddlyWiki's ImportTiddlers due to cross-domain restrictions
if(config.macros.fileImport) {
$.extend(config.macros.importTiddlers, config.macros.fileImport);
}
}
// hijack saveChanges to ensure SystemSettings is private by default
var _saveChanges = saveChanges;
saveChanges = function(onlyIfDirty, tiddlers) {
if(tiddlers && tiddlers.length == 1 &&
tiddlers[0] && tiddlers[0].title == "SystemSettings") {
var fields = tiddlers[0].fields;
delete fields["server.recipe"];
fields["server.bag"] = plugin.getCurrentBag("private");
fields["server.workspace"] = plugin.getCurrentWorkspace("private");
}
return _saveChanges.apply(this, arguments);
};
// ensure backstage is always initialized
// required to circumvent TiddlyWiki's read-only based handling
config.macros.backstageInit = {
init: function() {
showBackstage = true;
}
};
// disable evaluated macro parameters for security reasons
config.evaluateMacroParameters = "none";
var _parseParams = String.prototype.parseParams;
String.prototype.parseParams = function(defaultName, defaultValue, allowEval,
noNames, cascadeDefaults) {
if(config.evaluateMacroParameters == "none") {
arguments[2] = false;
}
return _parseParams.apply(this, arguments);
};
var _tabsMacro = config.macros.tabs.handler;
config.macros.tabs.handler = function(place, macroName, params) {
var newParams = [params[0]]; // keep cookie name
for(var i = 1; i < params.length; i += 3) {
var tabTitle = params[i + 2];
if(!plugin.isDisabledTab(tabTitle)){
newParams = newParams.concat(params[i], params[i + 1], tabTitle);
}
}
_tabsMacro.apply(this, [place, macroName, newParams]);
};
// disable ControlView for XHRs by default
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView", "false");
}
});
// TiddlyWeb adaptor currently still uses httpReq, which needs extra magic -- XXX: obsolete this!
var _httpReq = httpReq;
httpReq = function(type, url, callback, params, headers, data, contentType,
username, password, allowCache) {
headers = headers || {};
headers["X-ControlView"] = "false";
_httpReq.apply(this, arguments);
};
// register style sheet for backstage separately (important)
store.addNotification("StyleSheetBackstage", refreshStyles);
// option for default privacy setting
config.optionsDesc.chkPrivateMode = "Set your default privacy mode to private";
config.optionsSource.chkPrivateMode = "setting";
config.options.chkPrivateMode = config.options.chkPrivateMode || false;
saveSystemSetting("chkPrivateMode", true);
config.defaultCustomFields["server.workspace"] = plugin.
getCurrentWorkspace(config.options.chkPrivateMode ? "private" : "public");
config.paramifiers.follow = {
onstart: function(v) {
if(!readOnly) {
var bag = "%0_public".format(currentSpace);
story.displayTiddler(null, v, DEFAULT_EDIT_TEMPLATE, null, null,
"server.bag:%0 server.workspace:bags/%0".format(bag));
story.setTiddlerTag(v, "follow", 1);
story.focusTiddler(v, "text");
}
}
};
var fImport = config.macros.fileImport;
if(fImport) {
fImport.uploadTo = "Upload to: ";
var _createForm = config.macros.fileImport.createForm;
config.macros.fileImport.createForm = function(place, wizard, iframeName) {
var container = $("<div />").text(fImport.uploadTo).appendTo(place);
var select = $('<select name="mode" />').appendTo(container)[0];
$('<option value="private" selected>private</a>').appendTo(select);
$('<option value="public">public</a>').appendTo(select);
wizard.setValue("importmode", select);
_createForm.apply(this, [place, wizard, iframeName]);
};
var _onGet = config.macros.importTiddlers.onGetTiddler;
config.macros.importTiddlers.onGetTiddler = function(context, wizard) {
var type = $(wizard.getValue("importmode")).val();
var ws = plugin.getCurrentWorkspace(type);
wizard.setValue("workspace", ws);
_onGet.apply(this, [context, wizard]);
};
}
config.extensions.ServerSideSavingPlugin.reportSuccess = function(msg, tiddler) {
plugin.checkSyncStatus(tiddler);
msg = config.extensions.ServerSideSavingPlugin.locale[msg];
var link = "/" + encodeURIComponent(tiddler.title);
displayMessage(msg.format([tiddler.title]), link);
};
})(jQuery);
//}}}
<<tiddler FollowTemplate>>
emastic a CSS framework: http://code.google.com/p/emastic/
!Copy paste the following into "Edit Grammar" at:
http://railroad.my28msec.com/rr/ui .. do not include the tiddlyWiki {{{ {{{ and }}} }}}
{{{
/* <<list filter [tag[hugo 1]]>> */
/*
http://filters.tiddlyspace.com/#ExtraFiltersPlugin adds the following filters:
[is[image]] - returns only image tiddlers (e.g. png, jpeg, gif etc..)
[is[svg]] - returns only svg tiddlers
[notag[<tag>]] - filters result of previous filters for ones without a tag
[nofield[<field>]] - check for absence of field or field value in previous filters
[has[<field or attribute>]] - match tiddlers which have a field or attribute set.
[and[<filter expression>]] - e.g.[and[tag:foo]] checks all tiddlers from previous filters for a tag foo.
http://apm-plugins.tiddlyspot.com/#NumberedTextListPlugin%20XCaseListPlugin%20NoCaseListPlugin
<<list noCase title '[m]'>>
<<list numberedText sortField delimiter numberOfSections tagList>>
<<list xCase title '[0-9]'>>
*/
listMacro ::= '<< list' ( filter | 'all (default)' | 'missing' | 'orphans' | 'shaddowed' | 'touched')? '>>'
filter ::= 'filter' (('[' 'tag' '[' tagName ']]') | newFilter)? ('[' 'sort' '[' sortOrder (attribute | customField) ']]')?
sortOrder ::= ('-' | '+ (default)')?
attribute ::= 'title' | 'modified' | 'created' | 'modifier' | 'creator'
newFilters ::= is | noTag | noField | has | and
is ::= ('[' 'is' '[' knownMimeTypes ']]')? '<- image, svg are shorthands for content of server.content-type'
is ::= ('[' 'is' '[' (image | svg) ']]')?
noTag ::= ('[' 'notag' '[' tagName ']]')?
noField ::= ('[' 'nofield' '[' customField ']]')?
has ::= ('[' 'has' '[' (field | customField | attribute) ']]')?
has ::= ('[' 'has' '[' 'field:foo:value' ']]')? '<- discuss this !!!'
and ::= '[' 'and' '[' filterExpression ']]'
filterExpression ::= 'tag:foo <-- this seems to be inconsistent'
filterExpression ::= 'field:foo:value <-- will be needed too'
image ::= 'server.content-type [0-4] = image'
svg ::= 'server.content-type = image/svg+xml'
knownMimeTypes ::= image | svg
/* I know, that the following isn't true. Needs fixing */
customField ::= tagName
tagName ::= (Char)+
Char ::= [http://www.w3.org/TR/xml#NT-Char]
}}}
<<tiddler FollowTemplate>>
<<tiddler SidebarButtons>>
/%<<closeAll>><<permaview>><<newTiddler>><<newJournal 'YYYY, DD MMM'>>
%/
/*{{{*/
.cm-s-default span.cm-header {color: blue; font-weight:bold;}
.cm-s-default span.cm-code {color: #a50;}
.cm-s-default span.cm-code-inline {color: #660;}
.cm-s-default span.cm-quote {color: #555;}
.cm-s-default span.cm-list {color: #c60;}
.cm-s-default span.cm-hr {color: #999;}
.cm-s-default span.cm-em {font-style: italic;}
.cm-s-default span.cm-strong {font-weight: bold;}
.cm-s-default span.cm-link-external {color: blue;}
.cm-s-default span.cm-brace {color: #170; font-weight: bold;}
.cm-s-default span.cm-macro {color: #9E3825;}
.cm-s-default span.cm-table {color: blue; font-weight: bold;}
.cm-s-default span.cm-warning {color: red; font-weight: bold;}
.cm-s-default span.cm-underlined {text-decoration: underline;}
.cm-s-default span.cm-line-through {text-decoration: line-through;}
.cm-s-default span.cm-comment {color: #666;}
/*}}}*/
Some Text
!Others say
<<tsScan [[TestOthersSee]] fat:1 template:"TEMPLATES##scan" query:"select=bag:!pmario_public">>
!This is pmario's [[homespace|http://pmario.tiddlyspace.com]]
Have a look at my Projects@pmario at http://pmario.tiddlyspace.com/#Projects and have fun!
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" stroke="#4d4d4d">
<path id="path3288" style="stroke-dasharray:none;" d="m32.71,59.791a1.2868,1.2868,0,1,1,-2.5736,0,1.2868,1.2868,0,1,1,2.5736,0z" fill-rule="evenodd" transform="matrix(0.472928, 0, 0, 0.472928, 12.3536, 34.6064)" stroke-linecap="round" stroke-miterlimit="4" stroke-width="4" fill="#CCC"/>
<path id="path3637" style="stroke-dasharray:none;" d="m-5.7134,10.839a1.5781,1.5781,0,1,1,0.00225,-0.03585" transform="matrix(4.22706, 0, 0, 2.02533, 58.118, 41.1739)" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.68353766" fill="none"/>
<path id="path4348" d="m27.559,49.224,4.9188,2.0603-3.569,0,0.15291,6.0339-3.1302,0,0-6.0339-3.514,0,5.1416-2.0603z" stroke-linecap="butt" stroke-width="0.70393437px" fill="#4d4d4d"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
click -> irc://irc.freenode.net/#tiddlywiki
click -> irc://irc.freenode.net/#tiddlyspace
/***
|''Name''|ActivityStreamPlugin|
|''Version''|0.5.4|
|''Description''|Provides a following macro|
|''Author''|Jon Robson|
|''Requires''|TiddlySpaceFollowingPlugin|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''Source''|https://github.com/jdlrobson/TiddlyWiki/raw/master/plugins/TiddlySpaceInstaller/ActivityStreamPlugin.js|
!Usage
{{{<<activity>>}}}
!!Supressing activity
You can supress notifications by id:
"plugin", "shadow", "standard", "follow", "followYou", "siteInfo", "siteIcon", "ownSiteIcon", "notify", "reply"
e.g. {{{ <<activity supress:siteIcon>> }}} will hide siteIcon activity from you.
!!Supressing people
{{{<<activity ignore:person}}} will ignore all activity where person is the subject of the activity. eg. person followed other-person will not appear in the feed.
!!Controlling displayed dates.
{{{<<activity timestampFormat:"<0hh o' clock>" headingFormat:"0DD/0MM" >>}}} will display date headings as date/month eg.
3rd of January would be displayed as 03/01. This particular timestamp example gives you the hour of the activity.
!!Even more content
{{{<<activity limit:no>>}}} will show you all possible activity in the last X days where X is set at a macro level (advanced developers should see config.macros.activity.RECENTNESS).
!StyleSheet
.activityStream .externalImage, .activityStream .image {
display: inline;
}
.feedItem .siteIcon {
display: inline;
}
.activityStream .error {
background-color: red;
color: white;
font-weight: bold;
}
.activityStream .feedItem {
list-style: none;
}
.activityStream .notification {
background-color: yellow;
color: black;
}
.activityStream .activityGroupTitle {
font-weight: bold;
margin-top: 8px;
}
.activityStream .feedItem {
margin-left: 8px;
}
!Code
***/
//{{{
(function($) {
var name = "StyleSheetActivityStream";
config.shadowTiddlers[name] = store.getTiddlerText(tiddler.title +
"##StyleSheet");
store.addNotification(name, refreshStyles);
var followMacro = config.macros.followTiddlers;
var tweb = config.extensions.tiddlyweb;
var tiddlyspace = config.extensions.tiddlyspace;
var scanMacro = config.macros.tsScan;
var modifierSpaceLink = "<<view modifier spaceLink>>";
var spaceTiddlyLink = "<<view server.bag spaceLink server.title>>";
var bagSpaceLink = "<<view server.bag spaceLink>>";
var bagSiteIcon = "<<view server.bag SiteIcon width:24 height:24 label:no preserveAspectRatio:yes>>";
var modifierSiteIcon = "<<view modifier SiteIcon width:24 height:24 label:no preserveAspectRatio:yes>>";
var timestamp = "[<<view modified date '0hh:0mm'>>]";
var replyLink = "<<view server.title replyLink>>";
config.shadowTiddlers.ActivityStreamTemplates = [
"!notify\n%3 {{notification{%0 %1 has modified %2 in %0 %1 and flagged it for your attention!}}} %8\n",
"!reply\n%3 {{notification{%0 %1 replied with %2 to your %4 %5 post.}}} %8\n",
"!userSiteIcon\n%3 %6 %7 has a new ~SiteIcon.\n",
"!spaceSiteIcon\n%3 %6 %7 updated the SiteIcon for the %0 %1 space.\n",
"!image\n%3 %6 %7 drew the image %2 in the %1 space.\n",
"!plugin\n%3 %6 %7 modified a plugin called %2 in the %0 %1 space.\n",
"!shadow\n%3 %6 %7 modified a shadow tiddler %2 in the %0 %1 space.\n",
"!geo\n%3 %6 %7 modified a geo tiddler called %2 in the %0 %1 space <<view title maplink 'view on map'>>. %8\n",
"!followYou\n%3 %0 %1 is now following you.\n",
"!follow\n%3 %0 %1 is now following %4 %5 <<view server.title link follow>>\n",
"!siteInfo\n%3 %6 %7 <<view server.bag spaceLink server.title label:described>> the %0 %1 space.\n",
"!video\n%3 %6 %7 modified a video entitled %2 in the %0 %1 space. %8\n",
"!standard\n%3 %6 %7 modified %2 in the %0 %1 space. %8\n"
].join("").format(bagSiteIcon, bagSpaceLink, spaceTiddlyLink, timestamp,
"<<view server.title SiteIcon width:24 height:24 label:no preserveAspectRatio:yes>>", "<<view server.title spaceLink>>",
modifierSiteIcon, modifierSpaceLink, replyLink);
story.refreshTiddler("ActivityStreamTemplates", null, true);
config.annotations.ActivityStreamTemplates = "This is a special tiddler used by the ActivityStreamPlugin. It is used for templating notifications. Templates at the top have preference over templates at the bottom.";
var macro = config.macros.activity = {
default_limit: 50,
templates: [],
init: function() {
var templates = [];
var regex = new RegExp(/^!(.*)\n/gm);
var text = store.getTiddlerText("ActivityStreamTemplates");
var match = regex.exec(text);
while(match) {
templates.push(match[1]);
match = regex.exec(text);
}
macro.templates = templates;
},
// order matters - earlier templates override older ones
RECENTNESS: 2, // in days
TIMESTAMP_FORMAT: "<0hh:0mm>",
info: {},
locale: {
pleaseWait: "please wait while we load your stream...",
errorLoading: "The activity stream failed to load. Please make sure you have an internet connection and try again.",
userHeading: "Below is the activity stream for spaces that this space follows with the follow tag. (%0/%1 spaces have been loaded)",
emptyStream: "Activity stream currently empty. (%0/%1 loaded)"
},
getTimeStamp: function() {
var today = new Date();
macro._lastRun = today.getTime();
var previous = new Date(today.setDate(today.getDate() - macro.RECENTNESS));
return previous.convertToYYYYMMDDHHMM();
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var container = $("<div />").text(macro.locale.pleaseWait).appendTo(place).
attr("refresh", "macro").attr("macroName", macroName).attr("paramString", paramString);
var space = tiddlyspace.currentSpace.name;
var options = macro.getOptions(paramString);
$(container).attr("activity-limit", options.limit);
macro._session = Math.random();
var activityType;
var sourceActivity = function(user) {
macro.CURRENT_USER = user.name;
macro.USER_AT_TAG = "@%0".format(user.name);
followMacro.getFollowers(function(users) {
macro.getActivity(container, users, activityType, options);
}, macro.CURRENT_USER);
container.attr("activity-type", activityType);
macro._renderStream(container, activityType, options);
};
if(options.user) {
sourceActivity({name: options.user});
} else {
sourceActivity({ name: tiddlyspace.currentSpace.name });
}
},
getOptions: function(paramString) {
var options = {};
var args = paramString.parseParams("name")[0];
var toMap = ["timestampFormat", "headingFormat", "limit", "user"];
var i;
for(i = 0; i < toMap.length; i++) {
var map = toMap[i];
options[map] = args[map] ? args[map][0] : false;
}
var supress = args.supress || [];
var templates = [];
var show = args.show ? args.show : macro.templates;
for(i = 0; i < show.length; i++) {
var template = show[i];
if(supress.indexOf(template) === -1) {
templates.push(template);
}
}
options.ignore = args.ignore || [];
options.templates = templates;
return options;
},
_getActivityQuery: function(user, timestamp) {
timestamp = timestamp || macro.getTimeStamp();
if(user) {
return "/bags/%0_public/tiddlers?select=modified:>%1".format(user, timestamp);
} else {
return false;
}
},
refresh: function(container) {
var type = $(container).attr("activity-type");
var limit = $(container).attr("activity-limit");
var options = macro.getOptions($(container).attr("paramString"));
options.limit = parseInt(limit, 10);
macro.renderStream(container, type, options);
},
getActivity: function(place, users, type, options) {
var i;
var timestamp = macro.activityTimestamp;
var firstRun = timestamp ? false : true;
macro.info.loaded = firstRun ? 0 : macro.info.loaded;
var afterAjax = function(tiddlers) {
if(firstRun) {
macro.info.loaded += 1;
}
macro.updateStream(tiddlers, type, options);
macro.renderStream(place, type, options);
};
var success = function(tiddlers) {
afterAjax(tiddlers);
};
var error = function() {
afterAjax([]);
};
if(macro._lastRun > new Date().getTime() - 300000) { // leave 5 minutes between calls
afterAjax([]);
return;
}
macro.info.queries = users.length;
for(i = 0; i < users.length; i++) {
var user = users[i];
ajaxReq({
url: macro._getActivityQuery(user, timestamp),
dataType: "json", success: success, error: error
});
}
macro.activityTimestamp = new Date().convertToYYYYMMDDHHMM();
},
reportError: function(place) {
var error = $("<div />").addClass("error").text(locale.errorLoading);
$(place).empty().append(error);
},
createFeedEntry: function(container, tiddler, options) {
var item = $("<li />").addClass("feedItem");
var content = $("<div />").appendTo(item);
var wikifyPlace = $("<span />").appendTo(content)[0];
var author = tiddler.modifier;
if(author && !options.ignore.contains(author)) {
$(container).append(item);
config.macros.view.views.activityItem(null, wikifyPlace, null, null, null, tiddler);
return item;
}
return false;
},
renderStream: function(place, type, options) {
window.clearTimeout(macro._renderTimeout);
macro._renderTimeout = window.setTimeout(function() {
macro._renderStream(place, type, options);
}, 100);
},
_renderStream: function(place, type, options) {
$(place).empty();
var limit = options.limit;
var container = $("<ul />").addClass("activityStream").appendTo(place);
var textHeading = macro.locale.userHeading.format(macro.info.loaded, macro.info.queries);
$("<li />").addClass("listTitle").text(textHeading).appendTo(container);
var tiddlers = store.sortTiddlers(store.filterTiddlers("[server.activity[true]]"), "-modified"); // TODO: sort headings instead if possible (conflicts with limit)
var headings = [];
var groups = {};
var processed = 0, i, j;
var atEndOfActivityFeed = true;
for(i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
if(options.templates.contains(tiddler.fields["server.activity.type"])) {
if(!limit || processed < limit) {
var modified = tiddler.modified;
if(modified) {
// format date.
var modifiedString = modified.formatString(options.headingFormat || config.macros.timeline.dateFormat);
if(headings.contains(modifiedString)) {
groups[modifiedString].push(tiddler);
} else {
headings.push(modifiedString);
groups[modifiedString] = [ tiddler ];
}
}
processed += 1;
} else {
atEndOfActivityFeed = false;
}
}
}
var somethingRendered;
for(i = 0; i < headings.length; i++) {
var heading = headings[i];
var _tiddlers = store.sortTiddlers(groups[heading], "-modified");
var headingEl;
if(_tiddlers.length > 0) {
headingEl = $("<li />").addClass("listTitle activityGroupTitle").text(heading).appendTo(container);
}
var rendered = [];
for(j = 0; j < _tiddlers.length; j++) {
var item = macro.createFeedEntry(container, _tiddlers[j], options);
if(item) {
rendered.push(item);
}
}
if(rendered.length === 0) {
headingEl.remove();
} else {
somethingRendered = true;
}
}
if(!somethingRendered) {
var msg;
if(macro.gotActivity) { // it has been run before
msg = macro.locale.emptyStream.format(macro.info.loaded, macro.info.queries);
} else {
msg = macro.locale.pleaseWait;
}
$(container).text(msg);
}
if(!atEndOfActivityFeed) { // show more button
$("<input />").attr("type", "button").val("more").click(function(ev) {
var currentLimit = $(place).attr("activity-limit");
var newLimit = parseInt(currentLimit, 10) + 50;
macro.default_limit = newLimit;
$(place).attr("activity-limit", newLimit);
macro.refresh(place);
}).appendTo(place);
}
this.gotActivity = true;
},
updateStream: function(jstiddlers, type, options) {
// assume already sorted.
var tiddlers = scanMacro._tiddlerfy(jstiddlers, options);
var _dirty = store.isDirty();
$.each(tiddlers, function(i, tid) {
var info = config.macros.view.activity.getActivityInfo(tid, options);
tid.fields["server.activity.type"] = info.type;
tid.fields["server.activity"] = "true";
if(!tid.tags.contains("excludeLists")) {
tid.title = tiddlyspace.getLocalTitle(tid.title, tid.fields["server.workspace"]);
tid.tags = tid.tags.concat(["excludeLists", "excludeMissing", "excludeSearch"]);
tid.fields.doNotSave = "true";
store.addTiddler(tid); // save caused unsaved changes alert and slowdown
}
});
store.setDirty(_dirty);
}
};
config.macros.view.views.activityItem = function(value, place, params, wikifier,
paramString, tiddler) {
var info = config.macros.view.activity.getActivityInfo(tiddler, {});
wikify(info.template, place, null, tiddler);
};
var helper = config.macros.view.activity = {
_isNotification: function(tiddler) {
return tiddler.tags.contains(macro.USER_AT_TAG) || tiddler.tags.contains("@all");
},
_repliesOn: function() {
return tiddlyspace.currentSpace.name === macro.CURRENT_USER;
},
types: {
video: function(tiddler) {
return tiddler.tags.contains("video");
},
geo: function(tiddler) {
return tiddler.fields["geo.lat"] && tiddler.fields["geo.long"];
},
siteInfo: function(tiddler) {
var title = tiddler.fields["server.title"];
return title === "SiteInfo";
},
userSiteIcon: function(tiddler) {
var modifierBag = "%0_public".format(tiddler.modifier);
var title = tiddler.fields["server.title"];
return title === "SiteIcon" && modifierBag === tiddler.fields["server.bag"];
},
spaceSiteIcon: function(tiddler) {
var title = tiddler.fields["server.title"];
return title === "SiteIcon"; // note userSiteIcon above does the bag check
},
shadow: function(tiddler) {
var title = tiddler.fields["server.title"];
return title in config.shadowTiddlers;
},
plugin: function(tiddler) {
return tiddler.tags.contains("systemConfig");
},
followYou: function(tiddler) {
var title = tiddler.fields["server.title"];
title = title.indexOf("@") === 0 ? title.substr(1) : title;
return tiddler.tags.contains("follow") && title === macro.USER_AT_TAG;
},
follow: function(tiddler) {
return tiddler.tags.contains("follow");
},
reply: function(tiddler) {
var title = tiddler.fields["server.title"];
var myTiddler = store.getTiddler(tiddler.title);
var myTiddlerIsOlder = myTiddler && myTiddler.modified < tiddler.modified;
return store.tiddlerExists(title) && myTiddlerIsOlder && helper._repliesOn(tiddler);
},
notify: function(tiddler) {
var title = tiddler.fields["server.title"];
var myTiddler = store.getTiddler(title);
var myTiddlerIsNewer = myTiddler && myTiddler.modified > tiddler.modified;
return helper._isNotification(tiddler) && helper._repliesOn(tiddler) && !myTiddlerIsNewer;
},
standard: function(tiddler) {
return true;
},
image: function(tiddler) {
return config.macros.image.isImageTiddler(tiddler);
}
},
// each type should point to a slice in ActivityStreamTemplates tiddler
getActivityInfo: function(tiddler, options) {
var repliesOn = tiddlyspace.currentSpace.name === macro.CURRENT_USER;
var activityType, i;
if(tiddler) {
for(i = 0; i < macro.templates.length; i++) {
var type = macro.templates[i];
if(!activityType && helper.types[type]) {
if(helper.types[type](tiddler)) {
activityType = type;
}
}
}
}
template = store.getTiddlerText("ActivityStreamTemplates##" + activityType) || locale.standardTemplate;
return activityType ? { template: template, type: activityType } : false;
}
};
config.macros.view.views.link = function(value, place, params, wikifier,
paramString, tiddler) {
var el = createTiddlyLink(place,value,true);
if(params[2]) {
$(el).text(params[2]);
}
};
config.macros.view.views.maplink = function(value, place, params, wikifier,
paramString, tiddler) {
var lat = tiddler.fields["geo.lat"];
var lng = tiddler.fields["geo.long"];
var label = params[2] || value;
if(lat && lng) {
$("<a />").attr("href", "http://maps.google.com/maps?saddr=%0,%1".format(lat, lng)).text(label).appendTo(place);
}
};
var _displayS = tiddlyspace.displayServerTiddler;
tiddlyspace.displayServerTiddler = function(src, title, workspace, callback) {
var localTitle = tiddlyspace.getLocalTitle(title, workspace);
var localTiddler = store.getTiddler(localTitle);
var _callback = function(src, tiddler) {
if(callback) {
callback(src, tiddler);
}
if(localTiddler) {
tiddler.fields["server.activity"] = "true";
tiddler.fields["server.activity.type"] = localTiddler.fields["server.activity.type"];
}
};
return _displayS.apply(this, [ src, title, workspace, _callback ]);
};
}(jQuery));
//}}}
>in reply to [[High Performance CSS]]@bengillies:
Seems to be interesting. Is there some more info available?
{{{
<<tsScan @groupie tag:list query:"select=modified:>20101116">>
===
<<tsScan @groupie tag:list template:"tsScanFilterTest##Template">>
/%
!Template
<<tsScan $1 tag:@news searchField:"modifier" template:"SearchTemplate">>
!Template1
<<tsScan $1 tag:@groupie searchField:"modifier" template:"SearchTemplate">>
!
%/
}}}
!1
<<tsScan @groupie tag:list template:"tsScanFilterTest##Template">>
!2
<<tsScan @groupie tag:list template:"tsScanFilterTest##Template1">>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#CC9900" offset="0"/>
<stop id="stop2" stop-color="#E8D18B" offset="0.66462"/>
<stop id="stop3" stop-color="#CC9900" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" stroke="#4d4d4d" stroke-linecap="butt" fill="none">
<rect id="rect3637" style="stroke-dasharray:none;" ry="0" height="13.033" width="13.033" stroke-miterlimit="4" y="51.156" x="21.11" stroke-width="1.3672"/>
<path id="path3639" d="m20.989,54.423,12.783,0" stroke-width="0.80000001px"/>
<path id="path3641" d="m21.256,57.619,12.783,0" stroke-width="0.80000001px"/>
<path id="path3643" d="m21.211,60.682,12.65,0" stroke-width="0.80000001px"/>
<path id="path3645" d="m18.032,10.562,0,16.034" transform="matrix(0.8, 0, 0, 0.8, 13, 43)" stroke-width="1px"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
! TiddlyWikiThemes
I learned about TW themes at [[MPTW]] - ~MonkeyPirateTiddlyWiki.
!! The TW Layout
The default TW layout is defined by PageTemplate, ViewTemplate, EditTemplate and the StyleSheet tiddler. If you want to change the default behaviour, of your TW, you can edit those shadow tiddlers.
''Or'', you can create a single tiddler, that contains all of them, using TW sections. You can see an example: NeUIemTheme@neui-em at neui-em space. It contains the template tiddlers, as sections (headings). TiddlyWiki's transclusion core mechanism can handle themes presented like this.
Themes can be actively changed at runtime. You can see a short [[neui-em intro video|https://www.youtube.com/watch?v=jTaovgc4V5w]] at ~YouTube. Theme switching is introduced there.
!! Important
If a theme tiddler is active with your TW, changing the default shadow tiddlers, has ''no effect'' anymore. You need to change the theme tiddler. ''Be aware, that you can mess up the theme, changing stuff there. Creating a backup, is highly recomended!''
Learn more about section handling at [[tiddler macro]]@tiddlywiki-com-ref
/*{{{*/
Background: #e7eaed
Foreground: #111317
PrimaryPale: #b1b9c4
PrimaryLight: #7c899c
PrimaryMid: #505a6a
PrimaryDark: #000000
SecondaryPale: #bac4b1
SecondaryLight: #8a9c7c
SecondaryMid: #5c6a50
SecondaryDark: #000000
TertiaryPale: #c4b1b8
TertiaryLight: #9c7c87
TertiaryMid: #6a5059
TertiaryDark: #000000
/*}}}*/
That's me, at http://a-pm.net
<<tiddler FollowTemplate>>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 40 40"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><defs><linearGradient id="lG3826" x1="7.0996" gradientUnits="userSpaceOnUse" y1="18.829" gradientTransform="matrix(1.5858347,0,0,1.8078238,1098.1851,351.13716)" x2="1.5461" y2="-0.95166"><stop stop-color="#000" offset="0"/><stop stop-color="#9c9b99" offset="1"/></linearGradient><linearGradient id="lG3828" y2="372.44" gradientUnits="userSpaceOnUse" y1="375.7" x2="1111.7" x1="1097.7"><stop style="stop-color:#ac9393;" offset="0"/><stop style="stop-color:#c8b7b7;" offset="1"/></linearGradient></defs><g transform="translate(-1080.9375,-357.3329)"><path style="stroke-width:0;stroke-miterlimit:4;fill:url(#lG3826);" d="m1080.9,357.32,39.996-0.0426-0.01,40.008c-15.507-25.519-15.36-25.95-39.988-39.965z"/><path style="stroke-dashoffset:0;stroke:#7aa3be;stroke-linecap:round;stroke-miterlimit:4;stroke-width:1.49999988;fill:#c1e6fd;" d="m1091.9,363.55c6.5716-6.4925,16.576-7.3925,23.147-0.90003,6.5717,6.4925,6.5717,17.019,0,23.511-4.4424-8.6113-12.288-15.713-23.147-22.611z"/><path style="stroke-dashoffset:0;stroke:#ce81b0;stroke-linecap:round;stroke-miterlimit:4;stroke-width:1.5;fill:#f4c4e2;" d="m1110.2,367.62c3.217,3.2168,3.217,8.4323,0,11.649-3.8194-4.2357-8.3307-8.1824-11.649-11.649,3.217-3.2168,8.4325-3.2168,11.649-0.00002z"/><path style="stroke-linejoin:bevel;stroke:#000000;stroke-linecap:round;stroke-dasharray:none;stroke-miterlimit:4;stroke-width:0.80000001;fill:url(#lG3828);" d="m1081,357.34c18.79,6.4752,32.53,16.56,39.894,39.892-11.19-17.028-14.878-19.19-27.352-14.96,6.2984-12.098,3.9371-13.19-12.542-24.932z"/></g></svg>
<<tiddler FollowTemplate>>
/***
|''Name''|TiddlySpaceFollowingPlugin|
|''Version''|0.7.1|
|''Description''|Provides a following macro|
|''Author''|Jon Robson|
|''Requires''|TiddlySpaceConfig TiddlySpaceTiddlerIconsPlugin ErrorHandler|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
!Usage
Tag a tiddler with "follow" to express a list of followers.
Using the {{{<<followTiddlers X>>}}}
will reveal the number of tiddlers with name X in the set of spaces the *current* user viewing your space follows.
{{{<<following jon>>}}} will list all the users following Jon.
{{{<<followers jon>>}}} will list all the followers of jon.
{{{<linkedTiddlers>>}}} will list all tiddlers across TiddlySpace linked to the current tiddler
{{{<linkedTiddlers follow:yes>>}}} will list all tiddlers across TiddlySpace that come from your list of followers
adds spaceLink view type {{{<<view server.bag spaceLink>>}}} creates a link to the space described in server.bag
{{{<<view server.bag spaceLink title>>}}} makes a link to the tiddler with title expressed in the field title in space server.bag
If no name is given eg. {{{<<following>>}}} or {{{<<follow>>}}} it will default the current user.
!StyleSheet
.followTiddlersList li {
list-style:none;
}
.followButton {
width: 2em;
}
.followTiddlersList li .siteIcon {
height:48px;
width: 48px;
}
#sidebarTabs .followers li a,
.followers .siteIcon,
.followers .siteIcon div {
display: inline;
}
.followTiddlersList li .externalImage, .followTiddlersList li .image {
display: inline;
}
.scanResults li {
list-style: none;
}
!Code
***/
//{{{
(function($) {
var LIMIT_FOLLOWING = 100;
var tweb = config.extensions.tiddlyweb;
var tiddlyspace = config.extensions.tiddlyspace;
var currentSpace = tiddlyspace.currentSpace.name;
var shadows = config.shadowTiddlers;
config.annotations.ScanTemplate = "This tiddler is the default template used in the display of tiddlers founding using the tsScan macro. To access attributes use the view macro e.g. {{{<<view title text>>}}}";
shadows.ScanTemplate = "<<view modifier SiteIcon width:24 height:24 spaceLink:yes label:no>> <<view title link>>";
shadows.FollowersTemplate = "<<view server.bag SiteIcon width:24 height:24 spaceLink:yes label:no>> <<view server.bag spaceLink>>";
shadows.FollowingTemplate = "<<view title SiteIcon width:24 height:24 spaceLink:yes label:no>> <<view title spaceLink>>";
shadows.FollowTiddlersBlackList = "";
shadows.FollowTiddlersHeading = "There are tiddlers in spaces you follow using the follow tag which use the title <<view title text>>";
shadows.FollowTiddlersTemplate = ["* <<view server.space SiteIcon width:24 height:24 spaceLink:yes label:no>> ",
"<<view server.space spaceLink title external:no>> modified by <<view modifier spaceLink>> ",
"in the <<view server.space spaceLink>> space (<<view modified date>> @ <<view modified date 0hh:0mm>>).\n"].join("");
var name = "StyleSheetFollowing";
shadows[name] = "/*{{{*/\n%0\n/*}}}*/".
format(store.getTiddlerText(tiddler.title + "##StyleSheet"));
store.addNotification(name, refreshStyles);
// provide support for sucking in tiddlers from the server
tiddlyspace.displayServerTiddler = function(src, title, workspace, callback) {
var adaptor = store.getTiddlers()[0].getAdaptor();
var localTitle = tiddlyspace.getLocalTitle(title, workspace);
var tiddler = new Tiddler(localTitle);
tiddler.text = "Please wait while this tiddler is retrieved...";
tiddler.fields.doNotSave = "true";
store.addTiddler(tiddler);
src = story.displayTiddler(src || null, tiddler.title);
tweb.getStatus(function(status) {
var context = {
host: tweb.host, // TODO: inherit from source tiddler?
workspace: workspace,
headers: { "X-ControlView": "false" }
};
var getCallback = function(context, userParams) {
var tiddler = context.tiddler;
tiddler.title = localTitle;
store.addTiddler(tiddler);
story.refreshTiddler(localTitle, null, true); // overriding existing allows updating
if(callback) {
callback(src, tiddler);
}
};
adaptor.getTiddler(title, context, null, getCallback);
});
};
tiddlyspace.scroller = {
runHandler: function(title, top, bottom, height) {
var i;
var handlers = tiddlyspace.scroller.handlers;
var tidEl = story.getTiddler(title);
if(tidEl) {
var topEl = $(tidEl).offset().top + 20;
if(top === false || (topEl > top && topEl < bottom)) {
var h = handlers[title];
for(i = 0; i < h.length; i++) {
h[i]();
}
tiddlyspace.scroller.clearHandlers(title);
}
} else {
tiddlyspace.scroller.clearHandlers(title);
}
},
clearHandlers: function(title) {
tiddlyspace.scroller.handlers[title] = [];
},
registerIsVisibleEvent: function(title, handler) {
tiddlyspace.scroller.handlers[title] = tiddlyspace.scroller.handlers[title] || [];
tiddlyspace.scroller.handlers[title].push(handler);
},
init: function() {
this.handlers = {};
this.interval = window.setInterval(function() {
var top = $(window).scrollTop();
var height = $(window).height();
var bottom = top + height;
var title;
for(title in tiddlyspace.scroller.handlers) {
if(title) {
tiddlyspace.scroller.runHandler(title, top, bottom, height);
}
}
}, 2000); // every 2 seconds check scroll position
}
};
tiddlyspace.scroller.init();
var followMacro = config.macros.followTiddlers = {
locale: {
followListHeader: "Here are tiddlers from spaces you follow using the follow tag which use this title.",
noTiddlersFromFollowers: "None of the spaces you follow contain a tiddler with this name.",
errorMessage: "There was a problem retrieving tiddlers from the server. Please try again later."
},
init: function() {
followMacro.lookup = {};
},
followTag: "follow",
getHosts: function(callback) {
tweb.getStatus(function(status) {
callback(tweb.host, tiddlyspace.getHost(status.server_host, "%0"));
});
},
getBlacklist: function() {
return store.getTiddlerText("FollowTiddlersBlackList").split("\n");
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var args = paramString.parseParams("anon")[0];
var containingTiddler = story.findContainingTiddler(place).getAttribute('tiddler');
var title = (args.anon && args.anon[0]) || tiddler.fields["server.title"] || tiddler.title;
var tid = store.getTiddler(title);
var user = params[1] || false;
if(tid) {
followMacro.makeButton(place, {
url: "/search?q=title:%22" + encodeURIComponent(title) + "%22",
containingTiddler: containingTiddler,
blacklisted: followMacro.getBlacklist(), title: title, user: user,
consultFollowRelationship: (args.follow &&
args.follow[0] === 'false') ? false : true });
}
},
makeButton: function(place, options) { // this is essentially the same code in TiddlySpaceFollowingPlugin
var title = options.title;
var blacklisted = options.blacklisted;
var tiddler = store.getTiddler(title);
var btn = $('<div class="followButton" />').addClass("notLoaded").appendTo(place)[0];
if(blacklisted.contains(title)) {
$(btn).remove();
return;
} else {
var user = options.user;
window.setTimeout(function() { // prevent multiple calls due to refresh
tiddlyspace.scroller.registerIsVisibleEvent(options.containingTiddler, function() {
var mkButton = function(followers, ignore) {
if(!followers && !ignore) {
$(btn).remove();
} else {
$("<a />").appendTo(btn);
var scanOptions = { url: options.url,
spaceField: options.spaceField || "bag", template: null, sort: "-modified",
callback: function(tiddlers) {
$(btn).removeClass("notLoaded");
followMacro.constructInterface(btn, tiddlers);
}
};
if(!ignore) {
scanOptions.showBags = followMacro._getFollowerBags(followers);
}
scanOptions.hideBags = [tiddler.fields["server.bag"]];
scanMacro.scan(null, scanOptions, user);
}
};
if(options.consultFollowRelationship) {
followMacro.getFollowers(mkButton);
} else {
mkButton([], true);
}
});
}, 1000);
}
},
constructInterface: function(container, tiddlers) {
var txt = tiddlers.length;
var className = txt > 0 ? "hasReplies" : "noReplies";
var el = $(story.findContainingTiddler(container));
$(container).empty().addClass(className);
var btn = $("<a />").addClass("followedTiddlers").text(txt).
click(function(ev) {
followMacro.followingOnClick(ev);
}).appendTo('<div class="followedTiddlers" />').appendTo(container)[0];
$.data(btn, "tiddlers", tiddlers);
},
followingOnClick: function(ev) {
var target = ev.target;
var locale = followMacro.locale;
var el = $('<div class="followTiddlersList" />')[0];
var popup = Popup.create(target,"div");
$(popup).addClass("taggedTiddlerList followList").click(function(ev) { // make it so only clicking on the document outside the popup removes the popup
if(ev.target.parentNode != document) {
ev.stopPropagation();
}
}).append(el);
var tiddlers = $.data(target, "tiddlers") || [];
scanMacro.template(el, tiddlers.slice(0,1), "FollowTiddlersHeading");
scanMacro.template(el, tiddlers, "FollowTiddlersTemplate");
if(tiddlers.length === 0) {
$("<li />").text(locale.noTiddlersFromFollowers).appendTo(el);
}
Popup.show();
ev.stopPropagation();
return popup;
},
_getFollowerBags: function(followers) { // XXX: private or not?
return $.map(followers, function(name, i) {
return name != currentSpace ? "%0_public".format(name) : null;
});
},
getFollowers: function(callback, username) {
// returns a list of spaces being followed by the existing space
var followersCallback = function(user) {
if(!user.anon) {
scanMacro.scan(null, {
url: "/search?q=bag:%0_public tag:%1 _limit:%2".format(user.name, followMacro.followTag, LIMIT_FOLLOWING),
spaceField: "title", template: null, cache: true,
callback: function(tiddlers) {
var followers = [];
for(var i = 0; i < tiddlers.length; i++) {
followers.push(tiddlyspace.resolveSpaceName(tiddlers[i].title));
}
callback(followers);
}
});
} else {
callback(false);
}
};
return !username ? tweb.getUserInfo(followersCallback) : followersCallback({ name: username });
}
};
var scanMacro = config.macros.tsScan = {
init: function () {
this.scanned = {};
},
_tiddlerfy: function(jsontiddlers, options) {
var tiddlers = [];
var spaceField = options.spaceField || "bag"; // TODO: phase out use view types instead
$.each(jsontiddlers, function(i, t) {
var use = false;
if(!options.showBags || (options.showBags && options.showBags.contains(t.bag))) {
use = true;
}
if(options.hideBags && options.hideBags.contains(t.bag)) {
use = false;
}
if(use) {
var spaceName = t[spaceField];
var tiddler = config.adaptors.tiddlyweb.toTiddler(t, tweb.host);
tiddler.fields["server.space"] = tiddlyspace.resolveSpaceName(spaceName);
tiddlers.push(tiddler);
}
});
return tiddlers;
},
_scanCallback: function(place, jsontiddlers, options) {
var locale = followersMacro.locale;
var tiddlers = scanMacro._tiddlerfy(jsontiddlers, options);
if(options.sort) {
tiddlers = store.sortTiddlers(tiddlers, options.sort);
}
if(options.filter) {
var _store = new TiddlyWiki();
config.lastStore = _store;
for(var i = 0; i < tiddlers.length; i++) {
var clone = tiddlers[i];
clone.title = tiddlyspace.getLocalTitle(clone.title, clone.fields['server.workspace']);
_store.addTiddler(clone);
}
tiddlers = _store.filterTiddlers(options.filter);
}
if(place) {
$(place).empty();
var list = $("<ul />").appendTo(place)[0];
scanMacro.template(list, tiddlers, options.template);
if(tiddlers.length === 0) {
$("<li />").text(options.emptyMessage || locale.noone).appendTo(list);
$(list).addClass("emptyList");
}
}
if(options.callback) {
options.callback(tiddlers);
}
},
constructSearchUrl: function(host, options) {
if(options.url) {
return options.url;
}
var inputs = options.searchValues;
var tag = options.tag;
var searchField = options.searchField || "title";
var searchQuery = [];
for(var i = 0; i < inputs.length; i++) {
searchQuery.push('%0:"%1"'.format(searchField, inputs[i]));
}
var query = searchQuery.join(" OR ");
query = tag ? "(%0) AND tag:%1".format(query, tag) : query;
query = options.query ? "%0;%1;".format(query, options.query) : query;
query = options.fat ? "%0&fat=1".format(query) : query;
return '%0/search?q=%1'.format(host, query);
},
scan: function(place, options) { // TODO: make use of list macro with url filter
var locale = followersMacro.locale;
options.template = options.template ? options.template : "ScanTemplate";
followMacro.getHosts(function(host, tsHost) {
$(place).text(followersMacro.locale.pleaseWait);
options = options ? options: {};
var url = scanMacro.constructSearchUrl(host, options);
if(options.cache && scanMacro.scanned[url]) {
var tiddlers = scanMacro.scanned[url].tiddlers;
var run = function(tiddlers) {
scanMacro._scanCallback(place, tiddlers, options);
};
if(tiddlers) {
run(tiddlers);
} else {
scanMacro.scanned[url].callbacks.push(run);
}
} else {
var callback = function(tiddlers) {
scanMacro._scanCallback(place, tiddlers, options);
};
if(scanMacro.scanned[url] && scanMacro.scanned[url].callbacks) {
scanMacro.scanned[url].callbacks.push(callback);
} else {
scanMacro.scanned[url] = {
callbacks: [callback]
};
}
ajaxReq({
url: url,
dataType: "json",
success: function(tiddlers) {
scanMacro.scanned[url].tiddlers = tiddlers;
var callbacks = scanMacro.scanned[url].callbacks;
while(callbacks.length > 0) {
callbacks.pop()(tiddlers);
}
},
error: function(xhr) {
$(place).empty();
$("<span />").addClass("annotation error").text(locale.error.format(xhr.status)).appendTo(place);
}
});
}
});
},
template: function(place, tiddlers, template) { // TODO: make use of list macro.
for(var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var item = $('<li class="spaceName" />').appendTo(place)[0];
var spaceName = tiddler.fields["server.space"] || "";
var templateText = store.getTiddlerText(template).replace(/\$1/mg, spaceName);
wikify(templateText, item, null, tiddler);
}
},
getOptions: function(paramString, tiddler) {
var args = paramString.parseParams("name", null, true, false, true)[0];
var options = { query: false, sort: false, tag: false, template: false, showBags: args.show || false,
hideBags: args.hide || false, filter: false, spaceField: "bag", searchField: "title", fat: false,
emptyMessage: false };
for(var name in args) {
if(name != "name") {
if(name == "fat") {
options[name] = true;
} else {
options[name] = args[name][0];
}
}
}
// if user has set searchField to modifier, then use the modifiers value if available otherwise use searchValues.
var searchField = options.searchField;
var searchValues = args[searchField] ? args[searchField] : args.searchValues;
// if neither of those were used use the first parameter
var defaultValues = tiddler ? [ tiddler.title ] : [];
options.searchValues = searchValues ? searchValues : ( args.name ? [args.name[0]] : defaultValues);
return options;
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var container = $("<div />").addClass("scanResults resultsArea").appendTo(place)[0];
var options = scanMacro.getOptions(paramString, tiddler);
scanMacro.scan(container, options);
}
};
var followersMacro = config.macros.followers = {
locale: {
loggedOut: "Please login to see the list of followers",
noSupport: "We were unable to retrieve followers as your browser does not support following.",
pleaseWait: "Please wait while we look this up...",
error: "Error %0 occurred whilst retrieving data from server",
noone: "None."
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var locale = followersMacro.locale;
var args = paramString.parseParams("name", null, true, false, true)[0];
var username = args.name ? args.name[0] : false;
var container = $('<div class="followers" />').text(locale.pleaseWait).
appendTo(place)[0];
var followersCallback = function(user) {
if(user.anon) {
$("<span />").text(locale.loggedOut).appendTo(container);
} else {
var options = scanMacro.getOptions(paramString);
$.extend(options, {
url: "/search?q=title:@%0 OR title:%0 tag:%1 _limit:%2".
format(user.name, followMacro.followTag, LIMIT_FOLLOWING),
spaceField: "bag",
template: options.template ? options.template : "FollowersTemplate"
});
scanMacro.scan(container, options);
}
};
return !username ? followersCallback({ name: currentSpace }) : followersCallback({ name: username });
}
};
var followingMacro = config.macros.following = {
locale: {
pleaseWait: followersMacro.locale.pleaseWait,
loggedOut: "Please login to see who you are following",
noSupport: followersMacro.locale.noSupport,
error: followersMacro.locale.error,
noone: followersMacro.locale.noone
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var locale = followingMacro.locale;
var args = paramString.parseParams("name", null, true, false, true)[0];
var fat = args.fat ? true : false;
var username = args.name ? args.name[0] : false;
var container = $('<div class="following" />').text(locale.pleaseWait).
appendTo(place)[0];
var followingCallback = function(user) {
if(user.anon) {
$("<span />").text(locale.loggedOut).appendTo(container);
} else {
var options = scanMacro.getOptions(paramString);
$.extend(options, {
url: "/search?q=bag:%0_public tag:%1 _limit:%2".format(user.name, followMacro.followTag, LIMIT_FOLLOWING),
spaceField: "title",
template: options.template ? options.template : "FollowingTemplate"
});
scanMacro.scan(container, options);
}
};
return !username ? followingCallback({ name: currentSpace }) : followingCallback({ name: username });
}
};
var linkedMacro = config.macros.linkedTiddlers = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var args = paramString.parseParams("anon")[0];
var title = params[0] || tiddler.fields["server.title"] || tiddler.title;
var tid = store.getTiddler(title);
var containingTiddler = story.findContainingTiddler(place).getAttribute('tiddler');
if(tid) {
followMacro.makeButton(place, {
spaceField: "recipe",
url: "/bags/%0/tiddlers/%1/backlinks".format(tid.fields['server.bag'],
encodeURIComponent(tid.title)),
blacklisted: followMacro.getBlacklist(),
title: title,
containingTiddler: containingTiddler,
user: params[1] || false,
consultFollowRelationship: args.follow ? true : false });
}
}
};
if(config.options.chkFollowTiddlersIsLinkedTiddlers) {
merge(config.macros.followTiddlers, config.macros.linkedTiddlers);
config.shadowTiddlers.FollowTiddlersHeading = "These are the other tiddlers that link to this tiddler.";
}
})(jQuery);
//}}}
/*{{{*/
/*
Malo - CSS Library
Author:Vladimir Carrer
Version: 1.0 (beta)
Source/License: http://code.google.com/p/malo/
*/
/* CSS Reset */
/* not needed for TiddlyWiki
html, body, div, p{
margin: 0;
padding: 0;
border: 0;
}
*/
/* CSS Grid */
/*
For center layout
Define your default width in %, px or em
.main { margin:0 auto; width:85%;}
*/
.dp20,
.dp25,
.dp33,
.dp50,
.dp100{float:left; display: inline; *margin-left:-0.04em; } /* IE margin hack */
.dpfr{float:right;}
/* dp = div percet */
.dp20{width:20%;}
.dp25{width:25%;}
.dp33{width:33.33%;}
.dp50{width:50%;}
.dp100{width:100%;}
.clear{ clear:both;}
/*}}}*/
Active user name: <<option txtUserName>>
These options for customising [[TiddlyWiki]] are saved in your browser
select theme: <<selectTheme>>
select palette: <<selectPalette>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]
----
Also see [[AdvancedOptions]]
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
in reply to [[fnd|sync: deletions and publishing]]@fnd:
!!!My thoughts
1.) The local copy tiddler driven approach leaves no trace - OK
1.1.) A plugin is needed - OK
1.2.) ServerSideSavingPlugin overwrites removeTiddler method, flags as deleted, keeps the tiddler - OK
1.2.1.) This causes problems with shadow tiddlers - OK
add 1.2.1
*That's why I'd use the [deleted] suffix approach + tag the tiddler "deleted", which makes it possible, to reactivate a deleted tiddler.
**Which imo is a new feature :)
**Ask the user, if s/he wants to move the tiddler to trashcan or delete
***If delete .. delete the content, and mark the tiddler for sync/deletion
*The tag makes it possible, to get a nice {{{<<list filter [tag[deleted]]>>}}}.
*At the serverside TS there is the new "_archive" bag. That's why a locally deleted tiddler may not be deleted.
**If so it may be only archived.
**Which makes the whole thing a standard sync case.
**And now, that it is a standard case it can be generalized.
new:1.2.2)
What if a local "foo" is deleted, a new "foo" is created and deleted again.
*Delete "foo [deleted]" and append [deleted] to new "foo".
**This is a standard syncing solution
***Since a local copy is saved on the harddisk, manually recovering any "foo [deleted]" is possible. Nothing gets lost.
new: 1.2.3
What if a local eg: "StyleSheet" is an inclusion, and not a shaddow tiddler
*It ''can't'' be locally deleted, it has to be overwritten by an empty StyleSheet
**Otherwise after syncing, there will be unexpected results.
**The user has to be informed, and
**Only the content needs to be deleted.
*Since the tiddler is not deleted but changed, it is standard syncing solution
!!! Hidden tiddler wiht JSON or [deleted] suffix
I'd go for [deleted] suffix as written above
!!! Publishing in TiddlySpace
3.)
<<<
With regards to publishing in TiddlySpace, that's possibly more problematic, as it comprises a series of operations: Publishing a tiddler means first creating a single revision in the respective public workspace and then (only on success) deleting (or, in the future, moving) the private version.
It's not entirely clear yet how this could be modeled in a generic fashion.
<<<
!!!!A generic fashion idea.
May be deleting a tiddler can be treated the same way as moving a tiddler from one bag to an other.
*At the moment there is only the _archiv bag. Which is similar to a trashcan.
*May be in the future, there weill be the possibility ot Move a tiddler from one bag, to any other bag.
**See: [[Copy Tiddler to another space]]@tiddlyspace
eg:
* Local foo is private.
* Local foo should be public
** Rename it to: "foo [make-public]" and mark for syncing
** Since there needs to be a sync public mechanism, it is not new. It's cool.
* Local foo needs to be deleted.
** Rename it to: "foo [make-delete] and mark for syncing
*** If user wants to archiv it keep the content
*** If user wants to delete it delete the local content. Which also makes the TW file smaller.
* Local foo needs to be sent to archiv
** Rename it to: "foo [sendTo-archiv] and mark for syncing
* Local foo needs to be sent to any other space
** Rename it to: "foo [sendTo-@mySpaceNoTwo] and mark for syncing
The biggest advantage of this mechanism is, that you can see, what will happen, if you are online again.
!Others say
<<tsScan [[sync: deletions and publishing]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
chkPrivateMode: true
chkLoginTab: true
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns="http://www.w3.org/2000/svg" height="29pt" width="29pt" version="1.0" viewBox="13 43 29 29" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" gradientTransform="matrix(0, -0.544761, 0.529104, 0, 18.3357, 31.7966)" y1="27.646" x1="-57.66">
<stop id="stop3209" stop-color="#be7800" offset="0"/>
<stop id="stop3236" stop-color="#dcb400" offset="0.66462"/>
<stop id="stop3211" stop-color="#be7800" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4" fill-rule="evenodd">
<path id="iconBG" stroke-linejoin="round" style="stroke-dasharray:none;" d="m25.151,68.079,12.404-12.643c1.3742,0,2.4805,1.0369,2.4805,2.325v10.318c0,1.288-1.1063,2.325-2.4805,2.325h-9.9235c-1.3742,0-2.4805-1.0369-2.4805-2.325z" stroke="#696969" stroke-width="1.28" fill="none"/>
<path id="iconFG" stroke-linejoin="round" style="stroke-dasharray:none;" d="M27.143,67.989,37.527,57.183c0.69632,0,1.2569,0.52542,1.2569,1.1781v9.6286c0,0.65265-0.56057,1.1781-1.2569,1.1781h-9.1265c-0.69632,0-1.2569-0.52541-1.2569-1.1781z" stroke="#e6e6e6" stroke-width="0.96" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" transform="matrix(0.707107, 0.707107, -0.707107, 0.707107, 54.0298, -3.77985)" stroke="#4d4d4d" stroke-width="1.6" fill="#4d4d4d">
<path id="path3252" style="stroke-dasharray:none;" d="M34.232,64.294,36.834,61.791"/>
<path id="path3254" style="stroke-dasharray:none;" d="M36.834,61.791,34.232,59.34"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
!Followers
<<followers>>
!Activity
[[Replies and Notifications]]
<<activity>>
!Following
All spaces tagged follow
<<list filter [tag[follow]][sort[title]]>>
<<followSuggestions>>
Some time ago, there was a group discussion [[Use TW as a database|http://groups.google.com/group/tiddlywiki/browse_thread/thread/7af450269dfc771a/afa29cb3df3d1bb2]] which made me think a little bit about that.
First impression: It should be possible to create an app like the "paper tiger" with some intelligent tagging, and some interface.
Second impression: nope. You can't handle the tiddler names in an appropriate generaliced way. A world uniqe IDs would be needed. A little hack to test the idea: [[TiddlyWeb ID generator]]@paperstack.
Work's nice at [[continent]]@paperstack, but the tiddler title is not very handy.
=== stopped thinking here :(
in reply to [[fnd|sync: deletions and publishing]]@fnd:
<<<
I agree that suffixes are the way to go for deletions (which is one more reason to support something like server.page.id for diverging titles).
<<<
=== started thinking again :)
The problem for me is, that the programm needs the id and the user needs something readable. But TW makes it too easy to copy/paste tiddlers, which will destroy the eg: custom field, that holds the programm's ID.
Are there any plans have a "first class" universe ID ?
!Others say
<<tsScan [[TiddlyWebDatabase]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
! Taggly Tagging Styles for Neui-em Theme
TagglyTagging plugin comes with it's own shadow style sheet, which is created at plugin initialisation. TagglyTaggingStyles, is a bit messy but it is compatible with most of its common TW usecases, so I didn't change it too much. Just add the tiddly space specific stuff.
!! Visibility
Buttons are invisible by default (my personal preference), using the following line in TagglyTaggingStyles.
<<<
/*{{{*/
.tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }
/*}}}*/
<<<
just change it to the following line, if you want to have the taggly tagging toolbar allways visible.
<<<
/*{{{*/
.tagglyTagging .button { visibility:visible; margin-left:3px; margin-right:3px; }
/*}}}*/
<<<
Just an additional info: Buttons are activated, if the tiddler content is hovered with the mouse. The {{{.selected}}} CSS attribute is responsible for this behaviour.
<<<
/*{{{*/
.selected .tagglyTagging .button { visibility:visible; }
/*}}}*/
<<<
!! Color
The button color is defined by:
<<<
/*{{{*/
.tagglyTagging .button, .tagglyTagging .hidebutton {
color:[[ColorPalette::TertiaryLight]]; font-size:90%;
border:0px; padding-left:0.3em;padding-right:0.3em;
}
/*}}}*/
<<<
Where {{{[[ColorPalette::TertiaryLight]]}}} is a ~TiddlyWiki section definition, which is "transcluded" while the core activates all ~StyleSheets. It can be viewed with ViewColorPalette tiddler. You can either change ''all'' the {{{Tertiary...}}} definitions (they should fit together), or you can use {{{TertiaryMid or TertiaryDark}}}.
Be aware, that {{{Tertiary...}}} is used within the sidebar tabs too, so if you change the color, it affects the whole theme. This is by intention.
''A Hint:'' Don't set plugin related ~StyleSheet values to fixed (eg: #aabbcc) values, use the ColorPalette. It is more work at the moment, but it will bite you in the future if you don't.
/*{{{*/
#sidebar .wizard table {
margin: 0px;
}
#sidebarSearch {
margin: 0.2em 1em 0;
position: relative;
}
#sidebarSearch .txtOptionInput {
width: 100%;
margin-top: 5px;
}
#sidebarSearch .searchButton {
padding: 0.2em;
color: [[ColorPalette::Background]];
}
/* the borders look wrong with the body background */
#sidebar .button {
border-style: none;
}
/*-- new vor FreeStyle --*/
.tabContents {
overflow: auto;
}
#sidebarTabs .tabContents{
width: auto;
}
#sidebarTabs .sliderpanel a{
display: inline;
}
#sidebarTabs a.button,
#sidebarTools a.button {
margin:0 0.2em;
padding:0.2em 0.3em;
display:block;
}
.sidebarBox { /*-- new for FreeStyle --*/
padding-top: 0.3em;
}
/***
This fixes a problem with the tabs slider
***/
#sidebarTabs .button {
margin:0em 0.2em;
padding:0.2em 0.3em;
display:block;
}
#sidebarTools .sliderpanel,
#sidebarOptions .sliderpanel {
margin: 0 0.5em;
}
/* remove fixed size from inputs eg: search and password in sidebar */
.txtOptionInput, .pasOptionInput {
width: 90%;
}
/* adjust spacing for the above */
#sidebarOptions .input {
margin: 0.4em 5%;
}
/*}}}*/
! Stats Plugin
in reply to [[StatsPlugin]]@cdent:
@cdent wants to implement a "hit counter" for tiddlyweb using a redis database to store the stats.
I'm not sure, if a hit counter has any value. If I use a theme, that requests my avatar tiddler, everytime a page is shown, this avatar tiddler will get a lot of hits but it is only noise. Same with included TiddlyWiki themes and library tiddlers eg: jquery.js.
If something comes up, I'd expect a query syntax similar to the existing {{{search}}} or {{{hsearch}}} syntax. eg:
{{{
http://tiddlyspace.com/stats?q=bag:blog_public tag:post _limit:1000 &select=modified:>20130101 &select=modified:<20130131 &sort=-modified
}}}
* Which will show all tiddlers from bag {{{blog_public}}} which eliminates the "system bags" noise.
* I'm only interested in tiddlers that are tagged "post"
* {{{_limit}}} defines the number of tiddlers shown
* {{{&select}}} ... defines the time range
* {{{&sort}}} ... defines the sort order of the list eg: {{{+-hits}}}
or:
{{{
http://tiddlyspace.com/search.json?q=bag:blog_public tag:post stats:true _limit:1000 &select=modified:>20130101 &select=modified:<20130131 &sort=-modified
}}}
* see: {{{stats:true}}} which includes the statistic stuff into a tiddler representation.
How vimeo trys to attract new members
=====================================
Last night, two thing happened.
* youtube couldn't handle a video format anymore, that worked perfect in the past.
* I had to activate google+ to upload a video. wtf?
I activated it to upload some videos. I deactivated the google+ stuff from my profile and returned back to youtube. Now youtube is deactivated too. Hell - I really hate that style of business.
I had a look at vimeo.org - did sign up and uploaded a full HD video. They took it and told me that it will be rescaled to 720p and they told me I need to update to a paid account to get full HD back :( I could live with that ... but
The best thing is. If you want to try a new service because an existing one #$%&ยง$ you off, you get a "wait 45 minutes motivation penalty", just to see if they can handle your video format. - well done vimeo - I deleted the account - I'm so motivated that google get's me back.
have fun!
/%
!info
|Name|RefreshTiddler|
|Source|http://www.TiddlyTools.com/#RefreshTiddler|
|Version|2.0.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|transclusion|
|Description|create a link to force an immediate refresh of the current tiddler|
Usage
<<<
{{{
<<tiddler RefreshTiddler>>
<<tiddler RefreshTiddler with: label tip>>
}}}
<<<
Example
<<<
{{{<<tiddler RefreshTiddler with: "click me">>}}}
<<tiddler RefreshTiddler##show with: "click me">>
content displayed at <<today 0hh:0mm:0ss>>
<<<
!end
!show
<html><nowiki><a href="javascript:;" title="$2"
onclick="
var here=story.findContainingTiddler(this);
if (here) story.refreshTiddler(here.getAttribute('tiddler'),null,true);
return false;
">$1</a></html>
!end
%/<<tiddler {{var src='RefreshTiddler'; src+(tiddler&&tiddler.title==src?'##info':'##show')}}
with: {{'$1'!='$'+'1'?'$1':'refresh'}}
{{'$2'!='$'+'2'?'$2':'redisplay current tiddler content'}}
>>
/*{{{*/
Name:DarkerBlue
Background: #e3eaf2
Foreground: #0c141b
PrimaryPale: #ffffff
PrimaryLight: #adc3d9
PrimaryMid: #456688
PrimaryDark: #0a0f15
SecondaryPale: #ffffff
SecondaryLight: #bed9ad
SecondaryMid: #7eb35b
SecondaryDark: #223219
TertiaryPale: #ffffff
TertiaryLight: #d9adc7
TertiaryMid: #b35b90
TertiaryDark: #321928
Error: #f88
/*}}}*/
! Endless Loops with TagglyTagging "SiteMap" view
The TagglyTagging plugin doesn't handle circular tagging very well. An endless loop is created, if you activate the "SiteMap" view. see: [[Some problems in SUNYIT tiddlyspaces]]@sunyit-hypertextjournal ~@sunyit-
hypertextjournal
[[To Theme or Not to Theme, or How I โTricked Outโ (and reset) my Twiddlywiki.]]@sunyit-hypertextjournal ~@sunyit-
hypertextjournal seems to have circular tags. The tiddler should be just tagged "journal" ''and'' it's subtopics need to be adjusted too. eg: [[How Hard it Was]]@sunyit-hypertextjournal and [[Install Theme - pictures]]@sunyit-hypertextjournal. (I didn't dig deeper.)
! Breadcrumbs is good
I also think: ''~BreadCrumbs is good'' that's why I did include a placeholder div into the @neui-em theme. ~TiddlyTools breadcrumbs plugin contains some code, that searches for placeholder ID's. If it doesn't find any, it creates a breadcrumbs display area, which works well with TW default page layout. It didn't work well with, neui-em theme. I did implement this (undocumented feature), because I thought "it should just work".
see: NeUIemTheme@neui-em tiddler, near the end of the ~PageTemplate section.
<!--{{{-->
<!-- tsBoxBreadCrumbs -->
<div id='breadCrumbs' class='breadCrumbs box'></div>
<!--}}}-->
So it's a conincidence that [[BreadCrumbs is good]]@sunyit-hypertextjournal by @sunyit-corbetr works at his space. Editing the ~PageTemplate tiddler would work, if it would be used by neui-em theme. But I like the fact, that ''it just worked'' :)
! Overwriting String Prototype issue
I like the idea described at [[Standardizing Tiddlers with a Tiddly-based Form]]@sunyit-hypertextjournal but it overwrites the {{{String.prototype}}} in a different way, than the TW core does. So this may cause a problem in the future.
//{{{
//------------------------------------------------------------
// Trim Function - Removes Leading & Trailing Spaces
//------------------------------------------------------------
String.prototype.trim = function() {
return this.replace(/(^\s*)|(\s*$)/g,"");
}
//}}}
TW core implementation see: https://github.com/TiddlyWiki/tiddlywiki/blob/master/js/Strings.js#L12
Nice tiddler title
{{{**(@pmario)**@aassddff}}} .. seems to be valid syntax but isn't .. **(@pmario)**@aassddff
{{{[[**(@pmario)**]]@aassddff}}} .. valid syntax .. [[**(@pmario)**]]@aassddff
[[**(@pmario)**]] .. internal link .. OK.
<html>
<style>
#content {background-color: white;}
.important {background-color: yellow;}
.mySelected {
color: gray;
background-color: blue;
}
</style>
<div id="content"> <p>Some text<p>
<ul>
<li class="important">important text</li>
<li class="important">as important as .. </li>
</ul>
</div>
</html>
<script label="select first list element">
var li = jQuery('#content li');
// console.log(li)
jQuery(li[0]).toggleClass('mySelected');
</script>
<script label="select first content element">
jQuery('#content').toggleClass('mySelected');
</script>
----
<!--{{{-->
<html>
<style>
#content {background-color: white;}
.important {background-color: yellow;}
.mySelected {
color: gray;
background-color: blue;
}
</style>
<div id="content"> <p>Some text<p>
<ul>
<li class="important">important text</li>
<li class="important">as important as .. </li>
</ul>
</div>
</html>
<!--}}}-->
//{{{
<script label="select first list element">
var li = jQuery('#content li');
// console.log(li)
jQuery(li[0]).toggleClass('mySelected');
</script>
<script label="select first content element">
jQuery('#content').toggleClass('mySelected');
</script>
//}}}
<<tiddler ToggleLeftSidebarEm##show with: {{config.options.chkShowLeftSidebar?'โ':'โบ'}}{{config.options.chkShowRightSidebar?'hide':'show'}}>><<tiddler ToggleRightSidebarEm##show with: {{config.options.chkShowRightSidebar?'โบ':'โ'}}{{config.options.chkShowRightSidebar?'hide':'show'}}>><<slider chkSliderOptionsPanel OptionsPanel "ยป" "display the options panel">>
<<tiddler FollowTemplate>>
<<tiddler SidebarTools>>/%
If you prefere a Tools slider, use the line below
<<slider chkSliderToolsPanel SidebarTools "Tools ยป" "new, save, ...">>
%/
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
/***
|''Name''|zCodeMirrorPlugin|
|''Description''|Enables syntax highlighting for <pre> and <code> blocks. Adds a new formatter for {{{<code class='???'>}}}. Using the wonderfull CodeMirror library.|
|''Author''|PMario|
|''Version''|0.2.8|
|''Status''|''stable''|
|''Info''|CodeMirrorPluginInfo|
|''Source''|https://github.com/pmario/tw.CodeMirrorPlugin|
|''Documentation''|http://codemirror.tiddlyspace.com/|
|''License''|[[CC-BY-NC-SA|http://creativecommons.org/licenses/by-nc-sa/3.0/]]|
|''CoreVersion''|2.5.0|
|''Requires''|codemirror.js |
|''Keywords''|syntax highlighting color code mirror codemirror|
! Documentation
* ViewTemplate, EditTemplate and ToolbarCommands tiddler have to be adjusted. see: [[CodeMirrorPluginInfo]]
* Full info, see: [[CodeMirrorPluginInfo]]
! Usage
!!!! StyleSheet
<<<
* The plugin automatically creates a shadow tiddler: StyleSheetCodeMirror, that can be adjusted to your needs.
<<<
!!!! Macros
Modes: {{{<<cmModes>>}}} ... displays the usable modes seen below
<<<
Modes: <<cmModes>>
<<<
MIMEs: {{{<<cmMimes>>}}} ... displays the usable mime types seen below. Same order as modes.
<<<
Modes: <<cmMimes>>
<<<
MIMEs: {{{<<cmMimeObjects>>}}} ... displays the usable mime types seen below. Same order as modes. Shows the structure as a JSON.
<<<
<<cmMimeObjects>>
<<<
!!!!Global Settings
<<<
* Have a look at: [[CodeMirrorConfig]]
<<<
!!!! ViewTemplate
<<<
* Same as macro, but will be executed automatically for every tiddler. see: [[CodeMirrorPluginInfo]]
<<<
!!!! Parameters
<<<
{{{<<highlightSyntax [tagName]>> }}}
* will render all blocks, with any defined tag name. eg: tagName = {{{code}}}.
* [tagName] is optional. Default is "pre".
<<<
!!!! Configuration options
<<<
Guess syntax: <<option chkGuessSyntax>> .. If activated, ~TiddlyWiky <pre> blocks will be rendered according to there block braces. see [[CodeMirrorInfo]]
Expert mode: <<option chkExpertSyntax>> .. If activated, additional values below will be used. see [[CodeMirrorInfo]]
{{{ {{{ }}} txtShText: <<option txtShText>> eg: 'brush:text'
{{{ / *{{{* / }}} txtShCss: <<option txtShCss>> eg: 'brush:css'
{{{ //{{{ }}} txtShPlugin: <<option txtShPlugin>> 'brush:javascript'
{{{ <!--{{{-->> }}} txtShXml: <<option txtShXml>> 'brush:xml'
Additional options
<<<
!!!! Known Issues
* If you find something, just post at [[Google discussion group|http://groups.google.com/group/tiddlywiki?hl=en]]
* I'm happy to get some general feedback too!
!!!! Revision History
<<<
* V 0.2.8 2012-06-23
** "smartTab" handling adjusted. see: ExtraKeysAddOn
** minor documentation adjustments about ViewTemplate, EditTemplate requirements.
* V 0.1.0 2011-09-07
** inital release
see full History at CodeMirrorPluginInfo
<<<
!!! Code
!!!!! {{{<<cmModes>>, <<cmMimes>>, <<cmMimeObjects>>}}}
***/
//{{{
version.extensions.CodeMirrorPlugin = {major: 0, minor: 2, revision: 5, date: new Date(2012,2,7)};
(function($) {
config.macros.cmModes = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
jQuery('<span/>').text(CodeMirror.listModes().join(', ')).appendTo(place);
}
};
config.macros.cmMimes = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var cm = config.tools.cm;
jQuery('<span/>').text(cm.listMimeNames().join(', ')).appendTo(place);
}
};
config.macros.cmMimeObjects = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
jQuery('<span/>').text(JSON.stringify(CodeMirror.listMIMEs())).appendTo(place);
}
};
//}}}
/***
!!!!! Type chooser to define the MIME type
***/
//{{{
// create objects for typeChooser dropDown
config.macros.typeChooser = {};
config.views.editor.typeChooser = {};
// use this part if you need translation
merge(config.views.editor.typeChooser,{
text: "content-type",
tooltip: "Choose existing types to add to this tiddler",
popupNone: "There are no content-types defined",
typeTooltip: "Add the content-type '%0'"});
// content-type chooser
config.macros.typeChooser.onClick = function(ev)
{
var e = ev || window.event,
lingo = config.views.editor.typeChooser,
popup = Popup.create(this),
data = $(this).data('data'),
types = CodeMirror.listMIMEs();
types.push({mime: '-none-', mode: 'none'});
if(types.length === 0) {
$('<li/>').text(lingo.popupNone).appendTo(popup);
}
var t, type, mode, tooltipText;
for(t=0; t<types.length; t++) {
tooltipText = (typeof types[t].mode === 'object') ? types[t].mode.name : types[t].mode;
type = createTiddlyButton( createTiddlyElement(popup,'li'),
types[t].mime, lingo.typeTooltip.format([tooltipText]), config.macros.typeChooser.onTypeClick);
$(type).data('data', data);
type.setAttribute('type',types[t].mime);
type.setAttribute('tiddler',this.getAttribute('tiddler'));
}
Popup.show();
e.cancelBubble = true;
if(e.stopPropagation) {e.stopPropagation();}
return false;
};
config.macros.typeChooser.onTypeClick = function(ev)
{
var e = ev || window.event;
if(e.metaKey || e.ctrlKey) {stopEvent(e);} //# keep popup open on CTRL-click
var data = $(this).data('data'),
type = this.getAttribute('type'),
title = this.getAttribute('tiddler'),
conf = config.tools.cm.conf,
cm = config.tools.cm,
cmOptions = {},
mode;
// TODO doesn't seem to be right here.
// SyntaxHL change should work in read only too, for demo purpose.
if(!readOnly) {
// read actual global configuraiton
config.tools.cm.init();
// clear the input ..
$(data.input).val('');
if (type == '-none-' || type == 'content-type') {
story.setTiddlerField(title, '', '+1', data.ctfield);
}
else {
story.setTiddlerField(title, type, '+1', data.ctfield);
}
$(data.btn).text(type);
var text = $(story.getTiddler(title)).find('textarea[edit=text]');
var editor = $(text[0]).data('editor');
// save changes to textarea.
if (editor) {editor.save();}
// TODO if a tag overwrites the content-type, gray out/disable the content-type button.
if (editor) $(editor.getWrapperElement()).remove();
mode = cm.getModeObject(type);
$.extend( cmOptions, conf['global']);
$.extend( cmOptions, conf[mode.name]);
$.extend( cmOptions.mode, mode); // IMPORTANT overwrite mode, because it may be an object !!
var tid = store.getTiddler(title);
var cmField = story.hasTiddlerField(title, 'cm.height');
// if there is a cmField it will win, because there may be a new setting.
if (cmField) {
$.extend(cmOptions, {cmHeight: cmField.getAttribute('value')});
}
else if (tid && tid.fields['cm.height']) {
$.extend(cmOptions, {cmHeight: tid.fields['cm.height']});
} // TODO this code is used several times -> refactoring needed
cm.startEditor(text, cmOptions);
}
return false;
};
config.macros.typeChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var ctfield = params[0] || 'content-type';
if(tiddler instanceof Tiddler) {
var lingo = config.views.editor.typeChooser,
btnText = (tiddler.fields[ctfield]) ? tiddler.fields[ctfield] : lingo.text,
inpText = (tiddler.fields[ctfield]) ? tiddler.fields[ctfield] : '';
// createTiddlyElement(parent, element, id, className, text, attribs)
var $inp = $('<input type="text" edit="'+ctfield+'" size="20">').appendTo(place).val(inpText).hide();
var btn = createTiddlyButton(place, btnText, lingo.tooltip, this.onClick);
$(btn).data('data', {'input':$inp, 'btn':btn, 'ctfield':ctfield});
btn.setAttribute('tiddler', tiddler.title);
btn.setAttribute('exclude', params[0]);
}
};
//}}}
/***
!!!!! {{{<<highlightSyntax>>}}} macro
***/
//{{{
config.macros.highlightSyntax = {
getElementsByClass: function (searchClass,node,tag) {
var classElements = [];
if ( node === null ) {node = document;}
if ( tag === null ) {tag = '*';}
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp('(^|\\s)'+searchClass+'(:|\\s|$)');
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
},
// <<highlightSyntax tagName>>
// <<highlightSyntax code>> || <<highlightSyntax div>>
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
// the configured tagName can be temporarily overwritten by the macro.
var output, cStr, modeName;
var tagName = params[0] || 'pre';
var arr = this.getElementsByClass('brush', story.findContainingTiddler(place), tagName);
var src;
for (i=0; i<arr.length; i++) {
$output = $('<'+ tagName +' class="cm-s-default">'); // TODO theme handling
$src = $(arr[i]);
cStr = $src.attr('class');
cStr = cStr.parseParams(null, null, true);
modeName = getParam(cStr, 'brush', 'null');
CodeMirror.runMode($src.text(), modeName, $output[0]);
$src.replaceWith($output[0]);
}
} // handler
};
})(jQuery);
//}}}
/***
!!!!! New formatter for {{{<code class='brush:??'>}}}
***/
//{{{
config.formatters.push({
name: "highlightSyntax",
match: "^<code[\\s]+[^>]+>\\n",
element: "pre",
handler: function(w)
{
this.lookaheadRegExp = /<code[\s]+class.*=.*["'](.*)["'].*>\n((?:^[^\n]*\n)+?)(^<\/code>$\n?)/img;
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var options = lookaheadMatch[1];
var text = lookaheadMatch[2];
var cmMode;
if(config.browser.isIE) {
text = text.replace(/\n/g,"\r");
}
var element = createTiddlyElement(w.output,this.element,null,options +' cm-s-default',''); // TODO check for theme
// may be there will be additional params in the future.
cmMode = options.parseParams(null, null, true);
cmMode = getParam(cmMode, 'brush', 'null');
CodeMirror.runMode(text, cmMode, element);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
});
//}}}
/***
!!!!! Add class attribute to pre, if defined
***/
//{{{
(function(formatters) { //# set up alias
var helper = {};
helper.enclosedTextHelper = function(w){
var attr;
var co = config.options;
var expert = (co.chkExpertSyntax !== undefined)? co.chkExpertSyntax : false;
var guess = (co.chkGuessSyntax !== undefined)? co.chkGuessSyntax : true;
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE) {
text = text.replace(/\n/g,'\r');
}
switch(w.matchText) {
case '{{{\n': // text
attr = (expert) ? (co.txtShText) ? (co.txtShText) : 'text/plain' : 'text/plain' ;
break;
case '/*{{{*/\n': // CSS
attr = (expert) ? (co.txtShCss) ? (co.txtShCss) : 'css' : 'css';
break;
case '//{{{\n': // plugin
attr = (expert) ? (co.txtShPlugin) ? (co.txtShPlugin) : 'javascript' : 'javascript';
break;
case '<!--{{{-->\n': //template
attr = (expert) ? (co.txtShXml) ? (co.txtShXml) : 'xml' : 'xml';
break;
}
var element = createTiddlyElement(w.output,this.element,null,' cm-s-default',''); // TODO check for theme
if (guess || expert) {
CodeMirror.runMode(text, attr, element);
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
};
// merge the new helper function into formatterHelpers.
merge(config.formatterHelpers, helper);
})(config.formatters); //# end of alias
//}}}
/***
!!!!! CM tools and helper functions
***/
//{{{
(function ($) {
var me;
if (!config.tools) config.tools = {};
config.tools.cm = me = {
locale: {
},
// since TW layout is very flexible, the actual hight for the editor viewport can be guessed only
// formular used: window.height - title.h * 2 - toolbar.h * 2 - correction
// Editor scrolls into position, to be maximum visible.
// TODO correction may be given by the user. eg cookie
guessMaxHeight: function (corr) {
var wh = $(window).height(),
tih = ($('.title').height()) ? $('.title').height() : 0,
toh = ($('.toolbar').height()) ? $('.toolbar').height() : 0;
return wh - (tih + toh) * 2 - ((corr) ? corr : 0);
},
// This function is used, if there is a browser resize,
// or user want's to have max size
resizeEditor : function(height) {
var $cm = $('.CodeMirror');
$cm.width($cm.closest('.editor').width());
if (height) { $cm.find('.CodeMirror-scroll').height(height)};
},
listMimeNames: function() {
return CodeMirror.listMIMEs().map(function(el){return el.mime;});
},
getModeObject: function(mime) {
var arr = CodeMirror.listMIMEs();
var mode = {"name": 'null'};
for (var i=0, iMax = arr.length; i < iMax; i += 1) {
if (arr[i].mime == mime) {
if (typeof arr[i].mode === 'object') {
return arr[i].mode;
}
else if (typeof arr[i].mode === 'string' ) {
mode.name = arr[i].mode;
return mode;
} // else if
} // if
} // for
return mode;
},
helper : {
'true': true,
'false': false,
'null': null
},
calcTextSlices: function (text) {
var a = [], slices = {};
store.slicesRE.lastIndex = 0;
var m = store.slicesRE.exec(text);
while (m) {
if (m[2]) {
if (m[3] === '') {
slices[m[2]] = '';
}
else if (isNaN(m[3])) {
if (!slices[m[2]]) {
slices[m[2]] = (m[3] in me.helper) ? me.helper[m[3]] : m[3];
}
else {
if (typeof(slices[m[2]]) != 'string') {
slices[m[2]].push((m[3] in me.helper) ? me.helper[m[3]] : m[3]);
}
else {
a[0] = slices[m[2]];
slices[m[2]] = a;
slices[m[2]].push((m[3] in me.helper) ? me.helper[m[3]] : m[3]);
}
}
}
else {
slices[m[2]] = parseFloat(m[3]);
}
}
m = store.slicesRE.exec(text);
}
// console.log('slices: ', slices);
return slices;
},
rdSettings: function (cName) {
var settings = {};
var text;
var title = cName;
var secSep = config.textPrimitives.sectionSeparator;
var section = null;
var pos = title.indexOf(secSep);
if (pos != -1) {
section = title.substr(pos + config.textPrimitives.sectionSeparator.length);
title = title.substr(0, pos);
}
cName = (title) ? cName : tiddler.title + cName;
title = (title) ? title : tiddler.title;
if (store.tiddlerExists(title) || store.isShadowTiddler(title)) {
text = store.getTiddlerText(cName);
settings = me.calcTextSlices(text);
}
// special handling for functions.
// There are only extraKeys addOns at the moment !!
var p = ['extraKeys', 'onChange', 'onCursorActivity', 'onGutterClick', 'onFocus', 'onScroll', 'onHighlightComplete', 'onKeyEvent'];
var ctca = config.tools.cm.addOns;
var x;
for (var i = 0, im = p.length; i<im; i += 1) {
x = settings[p[i]];
if (x) {
// it's possible to have arrays of addOns
if (typeof(x) == 'object') {
settings[p[i]] = {};
for (var j = 0; j < x.length; j++) {
$.extend(settings[p[i]], (ctca && ctca[x[j]]) ? ctca[x[j]] : null);
}
}
else {
settings[p[i]] = (ctca && ctca[x]) ? ctca[x] : null;
}
}
}
return settings;
},
// stores the global CM config settings
conf: {},
init: function() {
var cm = 'CodeMirrorConfig', modes;
var secSep = config.textPrimitives.sectionSeparator;
// global settings need to be read seperately
me.conf['global'] = me.rdSettings(cm + secSep + 'global');
// check CM for installed modes and get usre config if available
modes = CodeMirror.listModes();
for (var i=0; i < modes.length; i += 1) {
me.conf[modes[i]] = me.rdSettings(cm + secSep + modes[i]);
}
},
startEditor: function(textArea, cmOptions) {
// disable chkInsertTabs
var height = null;
var co = config.options;
if (co.chkInsertTabs) {
// it's better to disalbe this option. see: smartTab mode.
$.extend(cmOptions.extraKeys, {"Tab": false, "Shift-Tab": false});
}
var editor = CodeMirror.fromTextArea(textArea[0], cmOptions);
$(textArea[0]).data('editor', editor);
if (cmOptions.cmHeight == 'max') {
$(editor.getScrollerElement()).data('oldHeight', $(editor.getScrollerElement()).height());
height = config.tools.cm.guessMaxHeight(25); // TODO 25 should be an option.
}
config.tools.cm.resizeEditor(height);
editor.focus();
editor.refresh();
}
}; // end plugin
// get and init the global CM settings
// config.tools.cm.init();
// Probably not needed with TiddlySpace themes.
// Deffinitely not needed with neui-em theme. The layout deals with it.
$(window).resize(function() {
config.tools.cm.resizeEditor();
});
})(jQuery);
//}}}
/***
!!!!! TiddlySpace specific stuff
***/
//{{{
// Check, if there is the BinaryTiddlersPlugin TODO and use it.
// If not check for content-type == text/....
(function($) {
var ctfield = 'content-type';
config.extensions.cm = me = {
isTW : function(ctype) {
return ctype.indexOf('tiddlywiki') != -1;
},
isTextual : function(ctype) {
return ctype.indexOf('text/') === 0
|| this.endsWith(ctype, '+xml')
|| ctype == 'application/json'
|| ctype == 'application/javascript';
},
endsWith: function(str, suffix) {
return str.length >= suffix.length &&
str.substr(str.length - suffix.length) == suffix;
}
};
// hijack text viewer to add special handling for binary tiddlers
var _view = config.macros.view.views.wikified;
config.macros.view.views.wikified = function(value, place, params, wikifier,
paramString, tiddler) {
var el;
var ctype = tiddler.fields[ctfield];
// TODO next line matches are ugly
if(params[0] == 'text' && ctype && !tiddler.text.match('{{'+'{') && !tiddler.text.match('<code')) {
if (!me.isTW(ctype) && me.isTextual(ctype)) {
el = $('<pre class="cm-s-default">').appendTo(place); // TODO theme
CodeMirror.runMode(tiddler.text, ctype, el[0]);
}
else { _view.apply(this, arguments);}
} // if
else {_view.apply(this, arguments);}
}; // _view
})(jQuery);
//}}}
/***
!!!!! The default StyleSheetCodeMirror style sheet
***/
//{{{
config.shadowTiddlers["StyleSheetCodeMirror"]="/*{{{*/\n"+
"[[codemirror.css]]\n"+
"[[tiddlywiki.css]]\n"+
"\n"+
".CodeMirror {\n"+
" border: 1px solid [[ColorPalette::PrimaryMid]];\n"+
" background: [[ColorPalette::Background]];\n"+
"}\n"+
"/*}}}*/";
store.addNotification("StyleSheetCodeMirror",refreshStyles);
//}}}
in reply to @cdent:
<<<
Despite what JonL says, the crux of the biscuit seems to be that some tiddlers are not saved, not that it takes a long time. ..snip.. -- @cdent
<<<
I experienced the same problem. What I did:
* opened Firebug and activated XHR display
* so you can see what's going on
* activated the "saveChanges" makro somewhere in the sidebar
* If XHR stops. push "saveChanges"
* repeat until all tiddlers are saved
* If you click "browser reload" and it tells you, some tiddlers are unsaved
* push "saveChanges" again ....
I managed to import about 360 tiddlers in one run, without anything lost. But it needed 3 attempts, to figure out how it works :)
!Others say
<<tsScan [[Importing large files]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
/*{{{*/
body {
font-size: 1.0em;
font-family: helvetica, arial, sans-serif;
background-color: [[ColorPalette::Background]];
}
#displayArea {
float: left; /*-- new for emastic --*/
padding: 0; /*-- new for emastic --*/
margin: 0; /*-- new for emastic --*/
}
#tiddlerDisplay {
/* margin: 1em 0.5em;*/
}
.public {
border-color: #C7EAFF;
}
.private {
border-color: #FFCAE9;
}
.revisionCloak {
position: absolute;
position: fixed !important;
height: 100%;
width: 100%;
top: 0;
left: 0;
border: 0;
margin: 0;
padding: 0;
opacity: 0.5;
filter: alpha(opacity=50);
background-color: black;
}
/* fixing h1-h6 margin-top if it is first child */
h1:first-child, h2:first-child, h3:first-child,
h4:first-child, h5:first-child, h6:first-child,
ol:first-child, ul:first-child {
margin-top: .3em;
}
[[StyleSheetHeaderMp]]
[[StyleSheetMenuBarMp]]
[[StyleSheetSideBarMp]]
[[StyleSheetTiddlerMp]]
[[StyleSheetBackstagePanels]]
/*}}}*/
!One thought
Some text, that is nice to read. The browser zoom level, in this window is 100%. It's about 20 words in one line. It's about 70 characters in one line.
For my taste, this layout is wasting about 2 1/2 cm of space on both sides. It is wasting about 1 cm on top of the note, since the dashboard and takenote menues could be integrated directly above the title.
I don't have any problem, if the default layout only uses about 15% of a given space. If someone tells me, how I can adjust it to my needs.
What I don't need, is an app, that tells me, that there is only one way it can be used.
/***
|''Name:''|FieldsEditorPlugin|
|''Description:''|//create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.|
|''Version:''|1.0.2|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demo:
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], see [[FieldEditor example]]
!Installation:
*import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
*save and reload
*optionnaly : add the following css text in your StyleSheet : {{{#popup tr.fieldTableRow td {padding:1px 3px 1px 3px;}}}
!Code
***/
//{{{
config.commands.fields.handlePopup = function(popup,title) {
var tiddler = store.fetchTiddler(title);
if(!tiddler)
return;
var fields = {};
store.forEachField(tiddler,function(tiddler,fieldName,value) {fields[fieldName] = value;},true);
var items = [];
for(var t in fields) {
var editCommand = "<<untiddledCall editFieldDialog "+escape(title)+" "+escape(t)+">>";
var deleteCommand = "<<untiddledCall deleteField "+escape(title)+" "+escape(t)+">>";
var renameCommand = "<<untiddledCall renameField "+escape(title)+" "+escape(t)+">>";
items.push({field: t,value: fields[t], actions: editCommand+renameCommand+deleteCommand});
}
items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
var createNewCommand = "<<untiddledCall createField "+escape(title)+">>";
items.push({field : "", value : "", actions:createNewCommand });
if(items.length > 0)
ListView.create(popup,items,this.listViewTemplate);
else
createTiddlyElement(popup,"div",null,null,this.emptyText);
}
config.commands.fields.listViewTemplate = {
columns: [
{name: 'Field', field: 'field', title: "Field", type: 'String'},
{name: 'Actions', field: 'actions', title: "Actions", type: 'WikiText'},
{name: 'Value', field: 'value', title: "Value", type: 'WikiText'}
],
rowClasses: [
{className: 'fieldTableRow', field: 'actions'}
],
buttons: [ //can't use button for selected then delete, because click on checkbox will hide the popup
]
}
config.macros.untiddledCall = { // when called from listview, tiddler is unset, so we need to pass tiddler as parameter
handler : function(place,macroName,params,wikifier,paramString) {
var macroName = params.shift();
if (macroName) var macro = config.macros[macroName];
var title = params.shift();
if (title) var tiddler = store.getTiddler(unescape(title));
if (macro) macro.handler(place,macroName,params,wikifier,paramString,tiddler);
}
}
config.macros.deleteField = {
handler : function(place,macroName,params,wikifier,paramString,tiddler) {
if(!readOnly && params[0]) {
fieldName = unescape(params[0]);
var btn = createTiddlyButton(place,"delete", "delete "+fieldName,this.onClickDeleteField);
btn.setAttribute("title",tiddler.title);
btn.setAttribute("fieldName", fieldName);
}
},
onClickDeleteField : function() {
var title=this.getAttribute("title");
var fieldName=this.getAttribute("fieldName");
var tiddler = store.getTiddler(title);
if (tiddler && fieldName && confirm("delete field " + fieldName+" from " + title +" tiddler ?")) {
delete tiddler.fields[fieldName];
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
story.refreshTiddler(title,"ViewTemplate",true);
}
return false;
}
}
config.macros.createField = {
handler : function(place,macroName,params,wikifier,paramString,tiddler) {
if(!readOnly) {
var btn = createTiddlyButton(place,"create new", "create a new field",this.onClickCreateField);
btn.setAttribute("title",tiddler.title);
}
},
onClickCreateField : function() {
var title=this.getAttribute("title");
var tiddler = store.getTiddler(title);
if (tiddler) {
var fieldName = prompt("Field name","");
if (store.getValue(tiddler,fieldName)) {
window.alert("This field already exists.");
}
else if (fieldName) {
var v = prompt("Field value","");
tiddler.fields[fieldName]=v;
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
story.refreshTiddler(title,"ViewTemplate",true);
}
}
return false;
}
}
config.macros.editFieldDialog = {
handler : function(place,macroName,params,wikifier,paramString,tiddler) {
if(!readOnly && params[0]) {
fieldName = unescape(params[0]);
var btn = createTiddlyButton(place,"edit", "edit this field",this.onClickEditFieldDialog);
btn.setAttribute("title",tiddler.title);
btn.setAttribute("fieldName", fieldName);
}
},
onClickEditFieldDialog : function() {
var title=this.getAttribute("title");
var tiddler = store.getTiddler(title);
var fieldName=this.getAttribute("fieldName");
if (tiddler && fieldName) {
var value = tiddler.fields[fieldName];
value = value ? value : "";
var lines = value.match(/\n/mg);
lines = lines ? true : false;
if (!lines || confirm("This field contains more than one line. Only the first line will be kept if you edit it here. Proceed ?")) {
var v = prompt("Field value",value);
tiddler.fields[fieldName]=v;
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
story.refreshTiddler(title,"ViewTemplate",true);
}
}
return false;
}
}
config.macros.renameField = {
handler : function(place,macroName,params,wikifier,paramString,tiddler) {
if(!readOnly && params[0]) {
fieldName = unescape(params[0]);
var btn = createTiddlyButton(place,"rename", "rename "+fieldName,this.onClickRenameField);
btn.setAttribute("title",tiddler.title);
btn.setAttribute("fieldName", fieldName);
}
},
onClickRenameField : function() {
var title=this.getAttribute("title");
var fieldName=this.getAttribute("fieldName");
var tiddler = store.getTiddler(title);
if (tiddler && fieldName) {
var newName = prompt("Rename " + fieldName + " as ?", fieldName);
if (newName) {
tiddler.fields[newName]=tiddler.fields[fieldName];
delete tiddler.fields[fieldName];
store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
story.refreshTiddler(title,"ViewTemplate",true);
}
}
return false;
}
}
config.shadowTiddlers.StyleSheetFieldsEditor = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow td {padding : 1px 3px}\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow .button {border:0; padding : 0 0.2em}\n";
config.shadowTiddlers.StyleSheetFieldsEditor +="/*}}}*/";
store.addNotification("StyleSheetFieldsEditor", refreshStyles);
//}}}
/%
!info
|Name|ToggleRightSidebarEm|
|Source|http://hoster.peermore.com/recipes/TeamWork/tiddlers.wiki#ToggleRightSidebarEm|
|Version|0.1.0|
|Author|Mario Pietsch|
|Derived from:|http://www.tiddlytools.com/#ToggleRightSidebar|
|License|http://creativecommons.org/licenses/by-nc-sa/3.0/at/|
|~CoreVersion|2.6|
|Type|transclusion|
|Description|show/hide right sidebar (MainMenu) for FreeStyle Themes. Works only with EmasticSystem|
Usage
<<<
{{{
<<tiddler ToggleRightSidebarEm>>
<<tiddler ToggleRightSidebarEm with: label tooltip>>
<<tiddler ToggleRightSidebarEm with: {{config.options.chkShowRightSidebar?'โบ':'โ'}}{{config.options.chkShowRightSidebar?'hide':'show'}}>>
}}}
Try it: <<tiddler ToggleRightSidebarEm##show
with: {{config.options.chkShowRightSidebar?'โบ':'โ'}}>>
<<<
Configuration:
<<<
{{{
config.options.chkShowRightSidebar (true)
config.options.txtToggleRightSideBarLabelShow (โ)
config.options.txtToggleRightSideBarLabelHide (โบ)
}}}
<<<
!end
!show
<<tiddler {{
var co=config.options;
if (co.chkShowRightSidebar===undefined) co.chkShowRightSidebar=true;
getDP = function(name) {
var width = undefined;
var myregexp = /dp([\d]{1,3})/;
var elem = jQuery(name);
var text = elem.attr('class');
var match = myregexp.exec(text);
if (match != null) {
width = match[1];
} else {
elem = jQuery(name).parent();
text = elem.attr('class');
match = myregexp.exec(text);
if (match != null) {
width = match[1]
}
else elem = undefined;
}
return {'width': width, 'elem': elem};
}; // end function
setDP = function(cmd, elem, target) {
if (!elem || !target) return alert('elem or target undefined!');
var newWidth = 0;
if (cmd === 'hide' && (elem.elem.css('display') != 'none')) {
newWidth = parseInt(target.width) + parseInt(elem.width);
jQuery(elem.elem).hide();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
}; // end function
var mm = getDP('#mainMenu');
var da = getDP('#displayArea');
var sb = getDP('#sidebar');
var cmd = co.chkShowRightSidebar?'show':'hide';
setDP(cmd, sb, da);
'';}}>><html><nowiki><a href='javascript:;' title="$2"
onmouseover="
this.href='javascript:void(eval(decodeURIComponent(%22(function(){try{('
+encodeURIComponent(encodeURIComponent(this.onclick))
+')()}catch(e){alert(e.description?e.description:e.toString())}})()%22)))';"
onclick="
var co=config.options;
var opt='chkShowRightSidebar';
var show=co[opt]=!co[opt];
getDP = function(name) {
var width = undefined;
var myregexp = /dp([\d]{1,3})/;
var elem = jQuery(name);
var text = elem.attr('class');
var match = myregexp.exec(text);
if (match != null) {
width = match[1];
} else {
elem = jQuery(name).parent();
text = elem.attr('class');
match = myregexp.exec(text);
if (match != null) {
width = match[1]
}
else elem = undefined;
}
return {'width': width, 'elem': elem};
}; // end function
setDP = function(cmd, elem, target) {
if (!elem || !target) return alert('elem or target undefined!');
var newWidth = 0;
if (cmd === 'hide') {
newWidth = parseInt(target.width) + parseInt(elem.width);
jQuery(elem.elem).hide();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
else if (cmd === 'show') {
newWidth = parseInt(target.width) - parseInt(elem.width);
jQuery(elem.elem).show();
jQuery(target.elem).removeClass('dp'+target.width);
jQuery(target.elem).addClass('dp'+newWidth);
}
}; // end function
var mm = getDP('#mainMenu');
var da = getDP('#displayArea');
var sb = getDP('#sidebar');
var cmd = co.chkShowRightSidebar?'show':'hide';
setDP(cmd, sb, da);
saveOptionCookie(opt);
var labelShow=co.txtToggleRightSideBarLabelShow||'◄';
var labelHide=co.txtToggleRightSideBarLabelHide||'►';
if (this.innerHTML==labelShow||this.innerHTML==labelHide)
this.innerHTML=show?labelHide:labelShow;
this.title=(show?'hide':'show')+' Right sidebar';
var sm=document.getElementById('storyMenu');
if (sm) config.refreshers.content(sm);
return false;
">$1</a></html>
!end
%/<<tiddler {{
var src='ToggleRightSidebarEm';
src+(tiddler&&tiddler.title==src?'##info':'##show');
}} with: {{
var co=config.options;
var labelShow=co.txtToggleRightSideBarLabelShow||'◄';
var labelHide=co.txtToggleRightSideBarLabelHide||'►';
'$1'!='$'+'1'?'$1':(co.chkShowRightSidebar?labelHide:labelShow);
}} {{
var tip=(config.options.chkShowRightSidebar?'hide':'show')+' Right sidebar';
'$2'!='$'+'2'?'$2':tip;
}}>>
/***
https://github.com/tiddlyweb/chrjs/raw/master/main.js
***/
//{{{
// TiddlyWeb adaptor
// v0.14.3
/*jslint vars: true, unparam: true, nomen: true, white: true */
/*global jQuery */
var tiddlyweb = (function($) {
"use strict";
var tw = {
routes: {
// host is the TiddlyWeb instance's URI (including server_prefix)
// placeholders "_type" & "name" refer to the respective bag/recipe
root : "{host}/",
bags : "{host}/bags",
bag : "{host}/bags/{name}",
recipes : "{host}/recipes",
recipe : "{host}/recipes/{name}",
tiddlers : "{host}/{_type}s/{name}/tiddlers",
tiddler : "{host}/{_type}s/{name}/tiddlers/{title}",
revisions: "{host}/{_type}s/{name}/tiddlers/{title}/revisions",
revision : "{host}/{_type}s/{name}/tiddlers/{title}/revisions/{revision}",
search : "{host}/search?q={query}"
}
};
var convertTimestamp, supplant;
// host (optional) is the URI of the originating TiddlyWeb instance
tw.Resource = function(type, host) {
if(arguments.length) { // initialization
this._type = type;
if(host !== false) {
this.host = host !== undefined ? host.replace(/\/$/, "") : null;
}
}
};
$.extend(tw.Resource.prototype, {
// retrieves resource from server
// callback is passed resource, status, XHR (cf. jQuery.ajax success)
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
// filters is an optional filter string (e.g. "select=tag:foo;limit=5")
get: function(callback, errback, filters) {
var uri = this.route();
if(filters) {
var separator = uri.indexOf("?") === -1 ? "?" : ";";
uri += separator + filters;
}
var self = this;
return $.ajax({
url: uri,
type: "GET",
dataType: "json",
success: function(data, status, xhr) {
var resource = self.parse(data);
resource.etag = xhr.getResponseHeader("Etag");
callback(resource, status, xhr);
},
error: function(xhr, error, exc) {
errback(xhr, error, exc, self);
}
});
},
// sends resource to server
// callback is passed data, status, XHR (cf. jQuery.ajax success)
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
put: function(callback, errback) {
var self = this;
var options = {
url: this.route(),
type: "PUT",
contentType: "application/json",
data: JSON.stringify(this.baseData()),
success: function(data, status, xhr) {
callback(self, status, xhr);
},
error: function(xhr, error, exc) {
errback(xhr, error, exc, self);
}
};
if(this.ajaxSetup) {
this.ajaxSetup(options);
}
return $.ajax(options);
},
// deletes resource on server
// callback is passed data, status, XHR (cf. jQuery.ajax success)
// errback is passed XHR, error, exception, resource (cf. jQuery.ajax error)
"delete": function(callback, errback) {
var self = this;
var options = {
url: this.route(),
type: "DELETE",
success: function(data, status, xhr) {
callback(self, status, xhr);
},
error: function(xhr, error, exc) {
errback(xhr, error, exc, self);
}
};
if(this.ajaxSetup) {
this.ajaxSetup(options);
}
return $.ajax(options);
},
// returns an object carrying only the essential information of the resource
baseData: function() {
var data = {},
self = this;
$.each(this.data, function(i, item) {
var value = self[item];
if(value !== undefined) {
data[item] = value;
}
});
return data;
},
// returns corresponding instance from a raw object (if applicable)
parse: function(data) {
return data;
},
// list of accepted keys in serialization
data: [],
// returns resource's URI
route: function() {
return supplant(tw.routes[this._type], this);
}
});
var Container = function(type, name, host) {
if(arguments.length) { // initialization
tw.Resource.apply(this, [type, host]);
this.name = name;
this.desc = "";
this.policy = new tw.Policy({});
}
};
Container.prototype = new tw.Resource();
$.extend(Container.prototype, {
tiddlers: function() {
return new tw.TiddlerCollection(this);
},
parse: function(data) {
var type = tw._capitalize(this._type),
container = new tw[type](this.name, this.host);
data.policy = new tw.Policy(data.policy);
return $.extend(container, data);
},
data: ["desc", "policy"]
});
// attribs is an object whose members are merged into the instance (e.g. query)
tw.Collection = function(type, host, attribs) {
if(arguments.length) { // initialization
tw.Resource.apply(this, [type, host]);
$.extend(this, attribs);
}
};
tw.Collection.prototype = new tw.Resource();
tw.TiddlerCollection = function(container, tiddler) {
if(arguments.length) { // initialization
tw.Collection.apply(this, [tiddler ? "revisions" : "tiddlers"]);
this.container = container || null;
this.tiddler = tiddler || null;
}
};
tw.TiddlerCollection.prototype = new tw.Collection();
$.extend(tw.TiddlerCollection.prototype, {
parse: function(data) {
var container = this.container;
return $.map(data, function(item, i) {
var tiddler = new tw.Tiddler(item.title, container),
bag = item.bag;
tiddler = tw.Tiddler.prototype.parse.apply(tiddler, [item]);
if(!tiddler.bag && bag) { // XXX: bag always present!?
tiddler.bag = new tw.Bag(bag, container.host);
}
if(!tiddler.recipe && item.recipe) {
tiddler.recipe = new tw.Recipe(item.recipe, container.host);
}
delete item.recipe;
return $.extend(tiddler, item);
});
},
route: function() {
var params = this.container;
if(this.tiddler) {
var container = this.tiddler.bag || this.tiddler.recipe;
params = {
_type: container._type,
host: container.host,
name: container.name,
title: this.tiddler.title
};
}
return supplant(tw.routes[this._type], params);
}
});
tw.Search = function(query, host) {
tw.Collection.apply(this, ["search", host]);
this.query = query;
};
tw.Search.prototype = new tw.Collection();
$.extend(tw.Search.prototype, {
parse: function(data) {
this.container = { // XXX: hacky
_type: "bag",
host: this.host
};
var tiddlers = tw.TiddlerCollection.prototype.parse.apply(this, arguments);
delete this.container;
return tiddlers;
}
});
// title is the name of the tiddler
// container (optional) is an instance of either Bag or Recipe
// optionally accepts a single object representing tiddler attributes
tw.Tiddler = function(title, container) {
tw.Resource.apply(this, ["tiddler", false]);
this.title = title;
this.bag = container && container._type === "bag" ? container : null;
this.recipe = container && container._type === "recipe" ? container : null;
var self = this;
$.each(this.data, function(i, item) {
self[item] = undefined; // exposes list of standard attributes for inspectability
});
if(title && title.title) { // title is an object of tiddler attributes
$.extend(this, title);
}
};
tw.Tiddler.prototype = new tw.Resource();
$.extend(tw.Tiddler.prototype, {
revisions: function() {
return new tw.TiddlerCollection(this.bag || this.recipe, this);
},
route: function() {
var container = this.bag || this.recipe;
var params = $.extend({}, this, {
host: container ? container.host : null,
_type: this.bag ? "bag" : (this.recipe ? "recipe" : null),
name: container ? container.name : null
});
return supplant(tw.routes[this._type], params);
},
parse: function(data) {
var tiddler = new tw.Tiddler(this.title),
container = this.bag || this.recipe;
if(data.bag) {
tiddler.bag = new tw.Bag(data.bag, container.host);
delete data.bag;
}
delete data.recipe;
tiddler.created = data.created ? convertTimestamp(data.created) : new Date();
delete data.created;
tiddler.modified = data.modified ? convertTimestamp(data.modified) : new Date();
delete data.modified;
if(this.recipe) {
tiddler.recipe = this.recipe;
}
return $.extend(tiddler, data);
},
data: ["created", "creator", "modifier", "modified", "tags", "type", "text",
"fields"],
ajaxSetup: function(options) {
var self = this;
if(this.etag && (options.type === "PUT" || options.type === "DELETE")) {
options.beforeSend = function(xhr) {
xhr.setRequestHeader("If-Match", self.etag);
};
}
if(options.type === "PUT") {
var callback = options.success;
options.success = function(data, status, xhr) {
var loc = xhr.getResponseHeader("Location"),
etag = xhr.getResponseHeader("Etag");
if(loc && etag) {
self.etag = etag;
if(!self.bag) {
var bag = loc.split("/bags/").pop().split("/")[0];
self.bag = new tw.Bag(bag, self.recipe.host);
}
callback(self, status, xhr);
} else { // IE
self.get(callback, options.error);
}
};
}
}
});
tw.Revision = function(id, tiddler) {
var container = tiddler.bag || tiddler.recipe;
tw.Tiddler.apply(this, [tiddler.title, container]);
this._type = "revision";
this.revision = id;
};
tw.Revision.prototype = new tw.Tiddler();
$.extend(tw.Revision.prototype, {
revisions: false,
data: false,
put: false,
"delete": false
});
tw.Bag = function(name, host) {
Container.apply(this, ["bag", name, host]);
};
tw.Bag.prototype = new Container();
tw.Recipe = function(name, host) {
Container.apply(this, ["recipe", name, host]);
this.recipe = [];
};
tw.Recipe.prototype = new Container();
$.extend(tw.Recipe.prototype, {
data: ["recipe"].concat(Container.prototype.data)
});
tw.Policy = function(constraints) { // TODO: validation?
var self = this;
$.each(this.constraints, function(i, item) {
self[item] = constraints[item];
});
};
tw.Policy.prototype.constraints = ["read", "write", "create", "delete",
"manage", "accept", "owner"];
/*
* utilities
*/
tw._capitalize = function(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
// convert YYYYMMDDhhmmss timestamp to Date instance
convertTimestamp = function(t) {
if (t.match(/^\d{12,17}$/)) {
return new Date(Date.UTC(
parseInt(t.substr(0, 4), 10),
parseInt(t.substr(4, 2), 10) - 1,
parseInt(t.substr(6, 2), 10),
parseInt(t.substr(8, 2), 10),
parseInt(t.substr(10, 2), 10),
parseInt(t.substr(12, 2) || "0", 10),
parseInt(t.substr(14, 3) || "0", 10)
));
} else {
return new Date(Date.parse(t));
}
};
// adapted from Crockford (http://javascript.crockford.com/remedial.html)
supplant = function(str, obj) {
return str.replace(/{([^{}]*)}/g, function (a, b) {
var r = obj[b];
r = typeof r === "string" || typeof r === "number" ? r : a;
return $.inArray(b, ["host", "query"]) !== -1 ? r : encodeURIComponent(r); // XXX: special-casing
});
};
return tw;
}(jQuery));
//}}}
! ChatUps
<<fancyBox button:"Watch Chat Space" "loading.gif" label:"Open an iframe" href:"http://chat.tiddlyspace.com" defaults:"ChatUps##Iframe">>
! Iframe
{{{
width: 95%
height: 95%
centerOnScroll: true
transitionIn: none
transitionOut: none
type: iframe
}}}
!!!!!!end
{{{
<<fancyBox button:"Watch Chat Space" "loading.gif" label:"Open an iframe" href:"http://chat.tiddlyspace.com" defaults:"ChatUps##Iframe">>
}}}
/*{{{*/
Background: #e3eaf2
Foreground: #0c141b
PrimaryPale: #ffffff
PrimaryLight: #adc3d9
PrimaryMid: #5b87b3
PrimaryDark: #0a0f15
SecondaryPale: #ffffff
SecondaryLight: #bed9ad
SecondaryMid: #7eb35b
SecondaryDark: #0e150a
TertiaryPale: #ffffff
TertiaryLight: #d9adc7
TertiaryMid: #b35b90
TertiaryDark: #150a11
Error: #f88
ColorPaletteParameters: HSL([210|66], [0.36509835156374804],[0.06232365550379004|1])
/*}}}*/
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAHJgAAByYBOKZboAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANISURBVDiNVZNtaJVlGMd/9/2ct52XnXNszs0x3Ys1aqCzlpai9sJwVhRBQZHoBzEZsYEWWZAfAumNFrWWBUEhUcZhBBZNKmhC03FUKDJmOjc3szWWc+c5z563c87z3H0Ye+n6dHFx/a7r/+H/F0opltez+95ZHa9evSO+oqohWBavUUooK2dM2sbsVXvu2i8nPnx5cvm+WDjQ2toa3bCra0siXddZ3XRPixZWMdeWEceFguM7ti3mZkYv/O7emuiRuU/OZDJnbYAAgBBCHnjt+P6Kpm0d5RUV69Bimm2DbYHjgOsScxxu86Iba4tu7R1Ft6wX6F1UsPfFNx6sa3n6eKSisdYrSUwDbHsebq5xeeAuG7sg6O5LcPMWuPrE9aCReW7gm8OD2vDwcLyq+YmPo1UbWyxLI6+DOQemBQ81W+y622Z0MkA67rOhvsD3g2UYViLpmN7aU5m3+gKR1J1bwxWbtud1DduCsObTvt6mOl2iKuVx5LMklyc0UlGfYy/l2LPT5M3PYyi3dXtSO71NynjDZtNNBPQcJEMlOtp06iuLhDRFKAiWqcjn4PKYpPuLGE897LC20sP1EkGrULdZFgMrG2dnoX29yaHHdbKXQnR+kKLzvSQTU5IXnjQxDDDycKI/zB9XAxx53gRQTmlVo3RdqQwdTmUj+AquTATQczD9r+DVngS3rynRfp+LVwLfh6Ofxmio8ahd5YMUyIL+z1heh+ERje8GI+zZaVFyFUYeLl7R+Ko/wqHdFvGoQgi4OBJgx74Uf01LEZFTo9KfG88as7qv56D36yhCKPY+alMozH9cmLVvLSy6r1gSBNH9qDaelVrROSuMc6cNQ/H3lOD9L6PsfsSmvsZDCMibgse6UvT9FF6yr1CkAr/+rDmXzsiTJ982Qu7QUemO3EBB5scIYzcCdD5jLQIzObnYSwlRee16uZZ9fWAgMxcAcG5+O5hO1b1LKdjh+pVNB7vj85BYFhoBGhZhMf1nSjv/0Zr0K0NweClMbW0HkjNiS6vt1XXppZb7fRWOAAu6XSEKdjr421BEjPdWBS+c6+/vyf8vjQt/NrUdq/dU+t6CWLHO9ctrhBBKU/pkKJgbCav8+ewP+8dhCfoPMziEHvd5OQMAAAAASUVORK5CYII=
in reply to [[April Design - Themes and Personalisation]]@jon
<<<
* the interface of what we would build would allows basic customisation - a SiteIcon and SiteTitle
* it would allow the attachment of a stylesheet
* there is a concept of shadow tiddlers but a small amount of them
** at the moment such SiteIcon and SiteTitle may be of use.
<<<
I'd like to have a TW with less hard to maintain CSS.
<<<
* themes would not be able to introduce new components for consistency purpose. Might have a displayArea, title area, site icon area and side bar area. Cannot introduce new containers other than these. They are free to move these around the page however.
<<<
This would limit a lot of cool stuff, that is to be written in the future. :(
<<<
* theming is restricted by careful naming of classes on elements. It was pointed out that http://www.stubbornella.org/ has some good thoughts on this.
<<<
There are some very good points introduced there. But I personally don't like the class names. They are too long. But I like the idea to have a grid system, even if I use a different one :)
<<<
* In theming we want to avoid a culture where users have to resort to !important to change themes and override existing rules.
* single css tiddler for styling story to prevent confusion about where styling rules belong
<<<
A new CSS for TW would be easy, if there wouldn't be the backwards compatibility thing.
<<<
* themes cannot be set by plugins
<<<
I love my themes and I like many ideas from other themes. But introducing this, would cut my legs.
/***
|''Name''|BinaryUploadPlugin|
|''Version''|0.3.16|
|''Author''|Ben Gillies and Jon Robson|
|''Type''|plugin|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/BinaryUploadPlugin.js|
|''Description''|Upload a binary file to TiddlyWeb|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig TiddlyWebConfig|
!Usage
{{{
<<binaryUpload bag:<name> edit:tags edit:title tags:<default tags> title:<title> >>
}}}
* {{{bag:<name>}}}: optional; if left out, the file will be saved to the current workspace
* {{{edit:tags}}}: specifies that you want to tag the file being uploaded
* {{{edit:title}}}: specifies that you want to set the title to something other than the filename
* {{{tags:<default tags>}}}: specifies a default set of tags to apply to the file (requires {{{edit:tags}}} to be set)
* {{{title:<title>}}}: predefines the title of the binary tiddler
!Requires
TiddlyWeb
tiddlywebplugins.form
!Code
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace;
var macro = config.macros.binaryUpload = {
locale: {
titleDefaultValue: "Please enter a title...",
tagsDefaultValue: "Please enter some tags...",
titlePrefix: "title: ",
tagsPrefix: "tags: ",
loadSuccess: 'Tiddler %0 successfully uploaded',
loadError: "An error occurred when uploading the tiddler %0",
uploadInProgress: "Please wait while the file is uploaded...",
membersOnly: "Only members can upload."
},
renderInputFields: function(container, options) {
var locale = macro.locale;
var editableFields = options.edit;
var includeFields = {
tags: editableFields && editableFields.contains("tags") ? true : false,
title: editableFields && editableFields.contains("title") ? true : false
};
var fields = ["title", "tags"];
for(var i = 0; i < fields.length; i++) {
var fieldName = fields[i];
var userDefault = options[fieldName];
var defaultValue = userDefault ? userDefault[0] : false;
if(includeFields[fieldName] || defaultValue) {
var localeDefault = locale["%0DefaultValue".format(fieldName)];
var className = defaultValue ? "userInput" : "userInput notEdited";
var inputEl;
var val = defaultValue || localeDefault || "";
var iContainer = $("<div />").addClass("binaryUpload%0".format(fieldName)).
appendTo(container);
if(defaultValue && !includeFields[fieldName]) {
var label = locale["%0Prefix".format(fieldName)];
$("<span />").text(label).appendTo(iContainer);
$("<span />").addClass("disabledInput").text(val).appendTo(iContainer);
inputEl = $("<input />").attr("type", "hidden");
} else {
inputEl = $("<input />").attr("type", "text");
}
inputEl.attr("name", fieldName).
addClass("%0Edit".format(fieldName)).
val(val).addClass(className).appendTo(iContainer);
}
}
},
getTiddlerName: function(fileName) {
var fStart = fileName.lastIndexOf("\\");
var fStart2 = fileName.lastIndexOf("/");
fStart = fStart < fStart2 ? fStart2 : fStart;
fileName = fileName.substr(fStart+1);
return fileName;
},
errorHandler: function(fileName) {
displayMessage("upload of file %0 failed".format(fileName));
},
uploadFile: function(place, baseURL, workspace, options) {
var pleaseWait = $(".uploadProgress", place);
var iframeName = options.target;
var form = $("form", place);
var existingVal = $("input[name=title]", form).val();
var fileName = existingVal || $('input:file', form).val();
if(!fileName) {
return false; // the user hasn't selected a file yet
}
fileName = macro.getTiddlerName(fileName);
$("input[name=title]", place).val(fileName);
// we need to go somewhere afterwards to ensure the onload event triggers
var redirectTo = "/%0/tiddlers.txt?select=title:%1".
format(workspace, fileName);
var token = tiddlyspace ? tiddlyspace.getCSRFToken() : "";
var action = "%0?csrf_token=%1&redirect=%2"
.format(baseURL, token, redirectTo);
form[0].action = action; // dont use jquery to work with ie
form[0].target = iframeName;
// do not refactor following line... won't work in IE6 otherwise
$(place).append($('<iframe name="' + iframeName + '" id="' + iframeName + '"/>').css('display','none'));
macro.iFrameLoader(iframeName, function() {
var content = document.getElementById(iframeName).contentWindow.document.documentElement;
if($(content).text().indexOf(fileName) > -1) {
options.callback(place, fileName, workspace, baseURL);
} else {
macro.errorHandler(fileName);
}
form.show(1000);
pleaseWait.hide(1000);
});
form.hide(1000);
pleaseWait.show(1000);
return true;
},
createUploadForm: function(place, options) {
var locale = macro.locale;
if(readOnly) {
$('<div class="annotation" />').text(locale.membersOnly).
appendTo(place);
return;
}
var bag = options.bag;
options.callback = options.callback ? options.callback :
function(place, fileName, workspace, baseurl) {
macro.displayFile(place, fileName, workspace);
displayMessage(locale.loadSuccess.format(fileName));
$("input[type=text]", place).val("");
};
var defaults = config.defaultCustomFields;
place = $("<div />").addClass("container").appendTo(place)[0];
var workspace = bag ? "bags/%0".format(bag) : config.defaultCustomFields["server.workspace"];
var baseURL = defaults["server.host"];
baseURL += (baseURL[baseURL.length - 1] !== "/") ? "/" : "";
baseURL = "%0%1/tiddlers".format(baseURL, workspace);
//create the upload form, complete with invisible iframe
var iframeName = "binaryUploadiframe%0".format(Math.random());
// do not refactor following line of code to work in IE6.
var form = $('<form action="%0" method="POST" enctype="multipart/form-data" />'.
format(baseURL)).addClass("binaryUploadForm").
appendTo(place)[0];
macro.renderInputFields(form, options);
$(form).
append('<div class="binaryUploadFile"><input type="file" name="file" /></div>').
append('<div class="binaryUploadSubmit"><input type="submit" value="Upload" disabled /></div>').
submit(function(ev) {
this.target = iframeName;
options.target = iframeName;
macro.uploadFile(place, baseURL, workspace, options);
})
.find('[type="file"]').bind('change', function() {
$(form).find('[type="submit"]').prop('disabled', false);
}).end();
$('<div />').addClass("uploadProgress").text(locale.uploadInProgress).hide().appendTo(place);
$("input[name=file]", place).change(function(ev) {
var target = $(ev.target);
var fileName = target.val();
var title = $("input[type=text][name=title]", place);
if(!title.val()) {
title.val(fileName);
}
});
},
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
params = paramString.parseParams(null, null, true);
macro.createUploadForm(place, params[0]);
},
iFrameLoader: function(iframeName, callback) {
var iframe = document.getElementById(iframeName); //jQuery doesn't seem to want to do this!?
var locale = macro.locale;
$(".userInput").addClass("notEdited"); // reset editing
var finishedLoading = function() {
callback();
};
var iFrameLoadHandler = function() {
finishedLoading.apply();
return;
};
iframe.onload = iFrameLoadHandler;
//IE
completeReadyStateChanges = 0;
iframe.onreadystatechange = function() {
if (++(completeReadyStateChanges) == 3) {
iFrameLoadHandler();
}
};
},
displayFile: function(place, title, workspace) {
var adaptor = store.getTiddlers()[0].getAdaptor();
var context = {
workspace: workspace,
host: config.defaultCustomFields['server.host']
};
adaptor.getTiddler(title, context, null, function(context) {
if(context.status) {
store.addTiddler(context.tiddler);
story.displayTiddler(place, title);
var image = config.macros.image;
if(image && image.refreshImage) {
image.refreshImage("/%0/tiddlers/%1".format(workspace, title));
image.refreshImage(title);
image.refreshImage("/%0".format(title));
image.refreshImage("%0/%1/tiddlers/%2".format(config.extensions.tiddlyweb.host, workspace, title));
}
} else {
displayMessage(macro.locale.loadError.format(title));
}
});
}
};
if(tiddlyspace) {
config.macros.binaryUploadPublic = {
handler: function(place, macroName, params, wikifier, paramString, tiddler) {
var options = paramString.parseParams(null, null, true)[0];
var bag = tiddlyspace.getCurrentBag("public");
options.bag = bag;
macro.createUploadForm(place, options);
}
};
config.messages.privacySetting = config.options.chkPrivateMode ?
"private" : "public";
config.macros.binaryUpload.defaultWorkspace = tiddlyspace.
getCurrentWorkspace(config.messages.privacySetting);
}
})(jQuery);
//}}}
/***
|''Name''|LoadMissingExternalTiddler|
|''Version''|0.1.0|
|''Author''|Jon Robson|
***/
//{{{
var _loadMissing = Story.prototype.loadMissingTiddler;
Story.prototype.loadMissingTiddler = function(title,fields,callback) {
var matches = title.match(/([^\*]*) \*\(@([^\)]*)\)\*/);
if(matches && matches.length > 0) {
var sTitle = matches[1];
var space = matches[2]; config.extensions.tiddlyspace.displayServerTiddler(story.getTiddler(title),
sTitle, "bags/%0_public".format(space));
} else {
_loadMissing.apply(this, arguments)
}
};
//}}}
In reply to [[notabene]]@jon
You linked [[Friday 22nd]]@manifesto2 directly into @manifesto2. I discribed my first reaction at [[TWDev group|http://groups.google.com/group/tiddlywikidev/browse_thread/thread/cfac69ea57d4c617/8d416a1c79eecf68]].
Manifesto2 says:
<<<
a) A manifesto is a "public declaration of principles and intentions".
For TiddlySpace, this manifesto will describe and contextualize the
principles that will drive the next phase of development as well as
the long term purpose of the product and project.
b) It will not attend to the details of implementation but rather the
reasons for implementing at all. When done, if written well, it will
be a tool that helps participants judge what they should be doing and
if their solutions are appropriate. Not because the manifesto states
what must be done, but rather because it states the principles, goals
and values that form an ethos for the project. ....
<<<
Which in my opinion initiates a discussion about the "big picture" of ~TiddlySpace.
Your detailed view in [[Friday 22nd]]@manifesto2 confused me a little bit.
{{{
<<tsScan @pmario searchField:"tag" template:"SearchTemplate" sort:-modified>>
}}}
<<tsScan @pmario searchField:"tag" template:"SearchTemplate" sort:-modified>>
----
You need to include the @following space, that it works.
In reply to [[Changing the layout?]]@stevesuny at stevesuny
! Disable Sidebar Buttons
Changing the button menue back to text menues, just open the tiddler SidebarTools which is linked at [[Layout]] tiddler and remove the first line, which transcludes the buttons. The TW default text is still there but commented. Remove the comments too. See below
!!! SidebarTools content
<<<
{{{
<<tiddler SidebarButtons>>
/%<<closeAll>><<permaview>><<newTiddler>><<newJournal 'YYYY, DD MMM'>>
%/
}}}
<<<
''change to:''
<<<
{{{
<<closeAll>><<permaview>><<newTiddler>><<newJournal 'YYYY, DD MMM'>>
}}}
<<<
!!! CSidebarTools content
<<<
{{{
<<tiddler SidebarTools>>/%
If you prefere a Tools slider, use the line below
<<slider chkSliderToolsPanel SidebarTools "Tools ยป" "new, save, ...">>
%/
}}}
<<<
If you prefere sliders instead of a fixed menue just use the following lines. It will produce a ''Tools ยป'' and an ''Options ยป'' slider.
The special comment {{{/% %/}}} seen below, is just to cover the linebreaks, which would need some CSS tricks to remove them, so TW comments is easier.
<<<
{{{
<slider chkSliderToolsPanel SidebarTools "Tools ยป" "new, save, ...">>/%
%/<<slider chkSliderOptionsPanel OptionsPanel "Options ยป" "display the options panel">>
}}}
<<<
! ViewTemplate
It shouldn't be needed to edit any template, since I tried to move default ~TiddlyWiki template stuff into tiddlers. So most menu stuff can be changed, by editing tiddlers.
! Asking Questions
* Goggle [[TiddlySpace group|http://groups.google.com/group/tiddlyspace?hl=en]] or
* Goggle [[TiddlyWiki group|http://groups.google.com/group/tiddlywiki?hl=en]] will be fine for me.
! TW Theming
* I did a temporary 5 min hack for you at my asdf space http://asdf.tiddlyspace.com/ which I use for tests.
** In normal cases, this content should be there for a week or two.
* If you want to have a text only layout, you may want to use @nostalgia space.
** The "tab behaviour" can be switched off easily :)
** And since I do use the same tiddlers, it is even possible (for me), to switch between neui and nostalgia. But I think, I do have toolbar icons for both of them.
* TW theming is time consuming, and you have to "dive deep" into TW internals. So 4 hours is nothing ;)
! Question
Steve, do you want to get rid of the toolbar icons too?
# If so, I think I either need to create a new theme space. It was planned, to include icon spaces seperately but it would make the space handling more complicated, as it is allready. So I decided to copy them into the theme, which makes deleting them, a bit tricky :)
# Or I need to extend the TiddlySpaceToolbar plugin and hope, that the core devs accept the patch.
! Make Programm Look Big :)
<<tiddler TestTWCodeBlock "dp50">><<tiddler TestTWHighlightingEditor "dp50">><<tiddler TestTWCodeBlock "dp50">><<tiddler TestTWHighlightingEditor "dp50">><<tiddler TestTWCodeBlock "dp50">><<tiddler TestTWHighlightingEditor "dp50">>
/***
|''Name''|TiddlySpaceInitialization|
|''Version''|0.7.2|
|''Description''|Initializes new TiddlySpaces the first time they are created|
|''Status''|@@beta@@|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/blob/master/src/plugins/TiddlySpaceInit.js|
|''CoreVersion''|2.6.1|
|''Requires''|TiddlySpaceConfig RandomColorPalettePlugin chrjs ImageMacroPlugin|
!TODO
* robust error notification and recovery
!MarkupPreHead
<!--{{{-->
<link rel="shortcut icon" href="/recipes/%0_public/tiddlers/favicon.ico" />
<link href="/bags/%0_public/tiddlers.atom" rel="alternate"
type="application/atom+xml" title="%0's public feed" />
<link rel="canonical" href="%1/" />
<!--}}}-->
!Code
***/
//{{{
(function($) {
var versionField = "tiddlyspaceinit_version";
var markupPreHead = store.getTiddlerText(tiddler.title + "##MarkupPreHead", "");
var tiddlyspace = config.extensions.tiddlyspace;
var currentSpace = tiddlyspace.currentSpace;
var tweb = config.extensions.tiddlyweb;
var plugin = config.extensions.TiddlySpaceInit = {
version: "0.6",
SiteTitle: "%0",
SiteSubtitle: "a TiddlySpace",
flagTitle: "%0SetupFlag",
flagWarning: "Please do not modify this tiddler; it was created " +
"automatically upon space creation.",
dispatch: function(ev) {
var title = plugin.flagTitle.format([currentSpace.name]);
config.annotations[title] = plugin.flagWarning;
if(currentSpace.type != "private") {
return;
}
var tiddlers = [];
var tid = store.getTiddler(title);
if(tid) {
curVersion = parseFloat(tid.fields[versionField]);
reqVersion = parseFloat(plugin.version);
if(curVersion < reqVersion) {
plugin.update(curVersion, tid);
tid.fields[versionField] = plugin.version;
tid.incChangeCount();
tid = store.saveTiddler(tid);
tiddlers.push(tid);
}
} else { // first run
tid = new Tiddler(title);
tid.tags = ["excludeLists", "excludeSearch", "excludePublisher"];
tid.fields = $.extend({}, config.defaultCustomFields);
tid.fields[versionField] = plugin.version;
tid.text = "@@%0@@".format([plugin.flagWarning]);
tid = store.saveTiddler(tid);
tiddlers = tiddlers.concat(plugin.firstRun(), tid);
}
autoSaveChanges(null, tiddlers);
},
update: function(curVersion, flagTiddler) {
if(curVersion < 0.2) {
this.createAvatar();
}
if(curVersion < 0.3) {
flagTiddler.tags.pushUnique("excludePublisher"); // XXX: never persisted
}
if(curVersion < 0.5) { // v0.4 was faulty
this.setupMarkupPreHead();
}
if(curVersion < 0.6) {
this.purgeSystemSettings();
}
},
pubTid: {
tags: ["excludeLists", "excludeSearch"],
fields: $.extend({}, config.defaultCustomFields, {
"server.workspace": tiddlyspace.getCurrentWorkspace("public")
})
},
makeTiddlerIfNot: function(tiddler) {
if (!store.tiddlerExists(tiddler.title)) {
$.extend(true, tiddler, plugin.pubTid);
return [store.saveTiddler(tiddler)];
} else {
return [];
}
},
firstRun: function() {
var tiddlers = [];
// generate Site*itle
$.each(["SiteTitle", "SiteSubtitle"], function(i, item) {
var tid = new Tiddler(item);
tid.text = plugin[item].format([currentSpace.name]);
tiddlers.push.apply(tiddlers,
plugin.makeTiddlerIfNot(tid));
});
// generate public ColorPalette
var tid = new Tiddler("ColorPalette");
tid.text = config.macros.RandomColorPalette.generatePalette({
saturation_pale: 0.67, saturation_light: 0.53,
saturation_mid: 0.43, saturation_dark: 0.06,
pale: 0.99, light: 0.85, mid: 0.5, dark: 0.31
},
false);
tiddlers.push.apply(tiddlers, plugin.makeTiddlerIfNot(tid));
this.createAvatar();
this.setupMarkupPreHead();
return tiddlers;
},
// remove _cookie slices (TiddlyWiki 2.6.2 beta 6 remnants)
purgeSystemSettings: function() {
var ss = store.getTiddler("SystemSettings");
if(ss) {
var lines = ss.text.split("\n");
var persistentOptions = $.grep(lines, function(line, i) {
return line.indexOf("_cookie:") == -1;
});
ss.text = persistentOptions.join("\n");
ss = store.saveTiddler(ss);
autoSaveChanges(null, [ss]);
}
},
createAvatar: function() {
var avatar = "SiteIcon";
var host = tweb.host;
var notify = function(xhr, error, exc) {
displayMessage("ERROR: could not create avatar - " + // TODO: i18n
"%0: %1".format([xhr.statusText, xhr.responseText]));
// TODO: resolve!?
};
var pubBag = tiddlyspace.getCurrentBag("public");
var tid = new tiddlyweb.Tiddler(avatar);
tid.bag = new tiddlyweb.Bag(pubBag, host);
var callback = function(data, status, xhr) {}; // avatar already exists; do nothing
var errback = function(xhr, error, exc) {
if(xhr.status != 404) {
return;
}
// copy default avatar
var _notify = function(tid, status, xhr) {
displayMessage("created avatar"); // TODO: i18n
var image = config.macros.image;
if(image && image.refreshImage) {
var uri = "/%0/tiddlers/SiteIcon".
format(tiddlyspace.getCurrentWorkspace("public"));
image.refreshImage(uri);
image.refreshImage("SiteIcon");
}
};
var _callback = function(tid, status, xhr) {
tid.title = avatar;
tid.bag.name = pubBag;
delete tid.etag;
tid.put(_notify, notify); // TODO: add to current session document (via adaptor?)
};
tweb.getUserInfo(function(user) {
var avatarTitle = currentSpace.name == user.name ?
"defaultUserIcon" : "defaultSiteIcon";
var tid = new tiddlyweb.Tiddler(avatarTitle);
tid.bag = new tiddlyweb.Bag("common", host);
tid.get(_callback, notify);
});
};
tid.get(callback, errback);
},
setupMarkupPreHead: function() {
var pubWorkspace = tiddlyspace.getCurrentWorkspace("public");
var existing = store.getTiddler("MarkupPreHead");
if(!existing || existing.fields["server.workspace"] != pubWorkspace) {
tweb.getStatus(function(status) {
var tid = new Tiddler("MarkupPreHead");
tid.text = markupPreHead.format(currentSpace.name, tiddlyspace.getHost(status.server_host,
currentSpace.name));
tid.tags = ["excludeLists"];
tid.fields = $.extend({}, config.defaultCustomFields);
tid.fields["server.workspace"] = pubWorkspace;
tid.fields["server.page.revision"] = "false";
tid = store.saveTiddler(tid);
autoSaveChanges(null, [tid]);
});
}
}
};
$(document).bind("startup", plugin.dispatch);
})(jQuery);
//}}}
/***
|''Name''|AccessibleHeadingsPlugin|
|''Description''|formatter modifying TiddlyWiki's handling of headings|
|''Author:''|Pietsch Mario|
|''Version''|0.0.1|
|''Status''|@@experimental@@|
|''Source''||
|''Documentation''||
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
!!!Description
<<<
This formatter modifies the way headings are rendered in ~TiddlyWiki markup.
Since screen readers need h1-h3 to identify the document structure, the tiddler content should start with h4. So {{{! heading}}} will create a {{{<h4>}}} HTML element
{{{
! h4
!! h5
!!! h6
!!!! h6
!!!!! h6
!!!!!! h6
}}}
! h4
!! h5
!!! h6
!!!! h6
!!!!! h6
!!!!!! h6
<<<
!!! Revision History
<<<
!!!!V0.0.1 (2012-02-08)
* initial alpha release
<<<
***/
//{{{
(function(formatters) { //# set up alias
//remove one line break before heading.
var heading = formatters[formatters.findByField("name", "heading")];
merge( heading, {termRegExp: /(\n)/mg});
heading.match = "^!{1,6}";
heading.handler = function(w) {
var level;
level = (w.matchLength + 3 > 6)? 6 : w.matchLength + 3;
w.subWikifyTerm(createTiddlyElement(w.output,"h" + level), this.termRegExp);
};
})(config.formatters); //# end of alias
//}}}
/*{{{*/
#menuBar {
position: relative;
/* background-color: [[ColorPalette::PrimaryMid]];*/
min-height: 1em;
overflow: hidden;
font-size: 1.1em;
/* if you have a light bar border would be fine */
/*
border-top: 1px solid [[ColorPalette::PrimaryDark]];
border-bottom: 1px solid [[ColorPalette::PrimaryDark]];
*/
width: 100%; /* for ie 6 */
}
/* horizontal main menu stuff */
.topMenu, .topMenu a{
padding-top: 0.2em;
padding-bottom: 0.2em;
}
.topMenu ul,
.topMenu ol {
list-style:none;
padding:0;
margin: 0;
}
.topMenu li {
float: left;
}
#mainMenu {
width:auto; /*-- new in emastic --*/
position:relative; /*-- new in emastic --*/
text-align:right;
font-size:1.1em;
padding: 0.5em 0.5em 0; /* same as box */
}
#mainMenu a {
padding: 0.2em 0.2em;
}
#mainMenu a:hover {
background-color: [[ColorPalette::PrimaryMid]];
color: [[ColorPalette::Background]]
}
#sidebarOptions {
color: [[ColorPalette::PrimaryDark]];
}
#sidebarOptions {
min-height: 1em;
}
#sidebarOptions .button, #sidebarOptions .tiddlyLink, #sidebarOptions a,
.topMenu .button, .topMenu .tiddlyLink, .topMenu a {
margin-left: 0.5em;
margin-right: 0.5em;
padding-left: 3px;
padding-right: 3px;
color: [[ColorPalette::PrimaryPale]];
border: none;
display: inline;
}
#sidebarOptions .button:hover, #sidebarOptions .tiddlyLink:hover,
.topMenu .button:hover, .topMenu .tiddlyLink:hover {
color: [[ColorPalette::PrimaryDark]];
background: [[ColorPalette::PrimaryPale]];
}
/*}}}*/
I was looking for a browser notebook, with the possibility to work online and/or offline. And if possible with good syncing. I found http://lewcid.org/2009/02/03/a-busy-year-and-a-student-notebook/
Some more reading lead to a very active TiddlyWiki user group, and some specs about an alpha TiddlyWeb (mother of all server sides.) So I thought, let's see how fast the development is going on. That's it.
Learn more at: http://freestyle.tiddlyspace.com/
! ~CodeMirror Info
<<<
* Learn more at: http://codemirror.net/manual.html
* If this list is missing something, just have a look at the above page and add it :)
* Every parameter that is a (function) @@needs a corresponding CM addOn function@@ to work with TW.
* This tiddler is a shadow tiddler. If you mess it up, just delete it, and you'll get a "vanilla" copy :)
<<<
! Settings
<<<
If your mode is not listed here, the corresponding library is not included at your TW. See CodeMirrorPluginInfo tiddler at the "How to roll your own" section/heading.
''Possible Modes'' .. {{{<<cmModes>>}}}
><<cmModes>>
''Possible MIMEs'' .. {{{<<cmMimes>>}}}
><<cmMimes>>
<<<
!!! global
{{{
tabSize: 4
// (d) 4 .. if indentWithTabs is true, it should be same as indentUnit otherwise it behaves strange!
indentUnit: 4
// (d) 2 .. how many space a block is indented.
indentWithTabs: true
// (d) false || true
lineNumbers: true
// show line numbers
matchBrackets: true
// Determines whether brackets are matched whenever the cursor is moved next to a bracket.
electricChars: false
// Configures whether the editor should re-indent the current line, when an electric character is typed
extraKeys: smartTab
// IMPORTANT: chkInsertTabs cookie needs to be _de-activated_ otherwise extraKeys are ignored
// smartTab .. tab insert tab char. If text is selected tab indent block, shift-tab unindent block
// simpleTab .. tab insert tab char. If text is selected, it will bedeleted!
extraKeys: toggleMaxHeight
// F11 .. maximize editor height
}}}
!!! null
>default mode has an unlucky name
{{{
tags:
mode: text/plain
indentWithTabs: true
tabSize: 4
indentUnit: 4
}}}
!!! tiddlywiki
{{{
tags:
mode: tiddlywiki
indentWithTabs: true
tabSize: 4
indentUnit: 4
lineWrapping: true
}}}
!!! javascript
{{{
tags: systemConfig
mode: javascript
indentWithTabs: true
tabSize: 4
indentUnit: 4
electricChars: true
}}}
!!! xml
{{{
tags:
mode: xml
}}}
!!! css
{{{
tags: systemCSS
mode: css
}}}
!!! htmlmixed
{{{
tags: systemTheme
mode: htmlmixed
}}}
!!! python
{{{
tags:
mode: python
}}}
!!! xmlpure
{{{
tags:
mode: xmlpure
}}}
!!! php
{{{
tags:
mode: application/x-httpd-php
}}}
!!! clike
{{{
tags:
mode: clike
}}}
!!! stex
{{{
tags:
mode: stex
}}}
!!! haskell
{{{
tags:
mode: haskell
}}}
!!! ruby
{{{
tags:
mode: ruby
}}}
!!! smalltalk
{{{
tags:
mode: smalltalk
}}}
!!! plsql
{{{
tags:
mode: plsql
}}}
!!! lua
{{{
tags:
mode: lua
}}}
!!! scheme
{{{
tags:
mode: scheme
}}}
!!! rst
{{{
tags:
mode: rst
}}}
!!! yaml
{{{
tags:
mode: yaml
}}}
!!! sparql
{{{
tags:
mode: sparql
}}}
!!! velocity
{{{
tags:
mode: velocity
}}}
!!! r
{{{
tags:
mode: r
}}}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#6BB546" offset="0"/>
<stop id="stop2" stop-color="#B5DAA2" offset="0.66462"/>
<stop id="stop3" stop-color="#6BB546" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke="#4d4d4d" stroke-miterlimit="4" fill="none">
<path id="path3640" stroke-linejoin="round" style="stroke-dasharray:none;" d="m33.165,50.126-10.258,9.3293-2.0113,4.3956,4.2474-2.1224,9.8299-9.5985-1.8075-2.004z" stroke-linecap="butt" stroke-width="1.60000002"/>
<path id="path3642" stroke-linejoin="miter" style="stroke-dasharray:none;" d="m13.981,27.04,12.705,0" transform="matrix(0.8, 0, 0, 0.8, 13, 43)" stroke-linecap="round" stroke-width="2"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
!Upload an icon
<<tiddler spaceIcon>>
!Describe your space
If you haven't already done so, you should provide a brief decscription of yourself and what you're using this space for. To do this, just edit the [[SiteInfo]] tiddler (keeping the title the same of course).
!Change the title
<<tiddler spaceTitle>>
!Change the theme
<<tiddler colorScheme>>
!Change the menu
If you'd like to change the menu items along the top, you can edit the [[MainMenu]] tiddler.
!Change the default tiddlers
<<tiddler setDefaultTiddlers>>
!More Advanced customisations
If you know HTML and CSS, you can edit some or all of the following tiddlers to customise your space further:
* PageTemplate
* EditTemplate
* ViewTemplate
* StyleSheet
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="29pt" viewBox="13 43 29 29" width="29pt" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" onmousedown="if(jQuery) jQuery(document).trigger('cSmaller', {elem:this, comp:{animations:1}})" onmouseup="if(jQuery) jQuery(document).trigger('cResize', {elem:this, comp:{animations:1}})">
<defs id="defs6">
<linearGradient id="linearGradient001" y2="27.646" gradientUnits="userSpaceOnUse" x2="-45.8" y1="27.646" x1="-57.66">
<stop id="stop1" stop-color="#FF4646" offset="0"/>
<stop id="stop2" stop-color="#ffcccc" offset="0.66462"/>
<stop id="stop3" stop-color="#FF4646" offset="1"/>
</linearGradient></defs>
<g id="icon" stroke-linecap="round" stroke-miterlimit="4">
<rect id="iconBG" style="stroke-dasharray:none;" fill-rule="evenodd" ry="4.1663" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#696969" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="none"/>
<rect id="iconFG" stroke-width="0" fill-rule="evenodd" ry="2.3755" transform="matrix(0, -1, 1, 0, 0, 0)" width="22" stroke-miterlimit="4" y="16.646" x="-68.6" height="22" fill="url(#linearGradient001)" class="showOnHover" opacity="0"/>
<g id="iconSymbol" stroke-linejoin="miter" fill-rule="evenodd" stroke="#4d4d4d" stroke-linecap="round" stroke-miterlimit="4">
<g id="g3238" style="stroke-dasharray:none;" transform="matrix(0.302967, -0.302967, 0.302967, 0.302967, 7.05964, 37.1409)" stroke-width="3.19999981" fill="#e6e6e6">
<path id="path3240" style="stroke-dasharray:none;" d="m-7.3399,53.9,16.353,0"/>
<path id="path3242" style="stroke-dasharray:none;" d="m0.8368,62.077,0-16.353"/>
</g>
<g id="g3250" style="stroke-dasharray:none;" transform="matrix(0.302967, -0.302967, 0.302967, 0.302967, 7.05964, 45.7405)" stroke-width="3.19999981" fill="#e6e6e6">
<path id="path3252" style="stroke-dasharray:none;" d="m-7.3399,53.9,16.353,0"/>
<path id="path3254" style="stroke-dasharray:none;" d="m0.8368,62.077,0-16.353"/>
</g>
<g id="g3282" style="stroke-dasharray:none;" transform="matrix(0.302967, -0.302967, 0.302967, 0.302967, 15.4081, 37.1409)" stroke-width="3.19999981" fill="#e6e6e6">
<path id="path3284" style="stroke-dasharray:none;" d="m-7.3399,53.9,16.353,0"/>
<path id="path3286" style="stroke-dasharray:none;" d="m0.8368,62.077,0-16.353"/>
</g>
<path id="path3288" style="stroke-dasharray:none;" d="m32.71,59.791c0,0.71068-0.57612,1.2868-1.2868,1.2868s-1.2868-0.57612-1.2868-1.2868,0.57612-1.2868,1.2868-1.2868,1.2868,0.57612,1.2868,1.2868z" transform="translate(0.690476, 2.00866)" stroke-width="4" fill="#CCC"/>
</g>
<rect id="overlay" opacity="0.01" ry="4.1663" style="stroke-dasharray:none;" fill-rule="evenodd" transform="matrix(0, -1, 1, 0, 0, 0)" height="25" width="25" stroke="#e6e6e6" stroke-linecap="round" stroke-miterlimit="4" y="15.167" x="-70.116" stroke-width="1.2" fill="#e6e6e6" onmouseover="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})" onmouseout="if(jQuery) jQuery(document).trigger('cTglBg', {elem:this, comp:{animations:1}})"/>
</g>
</svg>
! Constraining shadow tiddlers
!!! [2011-11-03] In [[Feedback for Constraining shadow tiddlers]]@jon stated:
> Marking a tiddler with type text/x-shadow will make no difference to how the space looks compared to how it looks now. It will just be marked in a way that lets plugins know it is essential for the presentation of the TiddlyWiki.
I'm not sure, if {{{text/x-shadow}}} is the right marker. If I have an svg image, that is essential for space rendering it's type should be {{{image/svg+xml}}} (svg is only an example here. there are other conflicting types). How would you solve this?
!!! [2011-11-02] In response to: [[Constraining shadow tiddlers]]@jon
>I have been experimenting a lot recently with [[Bootstrapped TiddlyWiki]]. Basically what this does is load all tiddlers tagged excludeLists that are not known content types (e.g. html tiddlers, image tiddlers etc..)
I did work with tags, to identify system stuff, for my codemirror plugins, in the first run. I have to say, it doesn't work well. IMO tags are ment to be used for grouping topics together, at user level. Using it, to talk to the system causes trouble, over time. Working with "content-type" or "server.content-type" works well.
>The reason for doing this is that the TiddlySpace server will [[not scale well|We need to talk about TiddlyWiki]]@cdent and we need to change the ecosystem whilst sacrificing as little as possible. It is becoming clear to me that the only way to do this is if TiddlyWiki itself is a tiddler which loads other tiddlers.
I personally wouldn't have a problem, to download an "empty" TW skeleton file, that is connected to one or several spaces. The only thing needed, would be a working ''sync mechanism''
>It's working quite well in my space since I tag most of shadow tiddlers excludeLists - http://jon.tiddlyspace.com/_tiddlywiki
>It however doesn't work well on other spaces. If a ColorPalette isn't tagged excludeLists the ColorPalette doesn't get applied on startup. Things like [[chris's space|http://cdent.tiddlyspace.com/_tiddlywiki]] do not look like they [[should|http://cdent.tiddlyspace.com/tiddlers.wiki]]
See my first response. If a core dev has problems to get it working. Just think about standard users.
>The most sensible solution would be if all shadow tiddlers from now on had to have type text/x-shadow - the TiddlyWiki client could enforce this as could the TiddlyWeb client. If things do not have the right type things appear weird in the _tiddlywiki app.
Needs some thinking: Since any included space can be a "shadow space", just providing eg: plugins, CSS ...
But if you directly open the "shadow space", it is just a space. So marking something as "text/x-shadow" there may be wrong. (But need to think more about this)
> #@pmario #@cdent #@bengillies #@colmbritton #@jermolene
<<tiddler FollowTemplate>>
/*{{{*/
.headerForeground {
position: relative;
text-align: right;
}
.header {
width: 100%; /* for ie */
}
#contentWrapper {
position: relative;
padding-top: 1px;
top: -1px;
}
.header {
position: relative;
background-color: [[ColorPalette::PrimaryLight]];
}
.siteTitle {
display: block;
}
/*}}}*/
!Some more examples
In reply to [[formatting]]@espace ~@espace
!!How to display an asterisc in column 1
{{{
/%%/* the good
/%%/# the bad
/%%/! and the ugly
}}}
result:
<<<
/%%/* the good
/%%/# the bad
/%%/! and the ugly
<<<
!!Rendered blocks inside an executable tiddler tagged systemConfig
{{{
/***
Wikified comments, which are escaped from JavaScript interpreter, since it is a block comment
!Code
***/
//{{{
var a = b; // here comes the code. All of this is nicely executable, and rendered inside a pre.
//}}}
}}}
result:
<<<
/***
Wikified comments, which are escaped from JavaScript interpreter, since it is a block comment
!Code
***/
//{{{
var a = b; // here comes the code. All of this is nicely executable, and rendered inside a pre.
//}}}
<<<
!!Inside StyleSheets
{{{
/*{{{*/
.h1 {
}
/*}}}*/
}}}
result:
<<<
/*{{{*/
.h1 {
}
/*}}}*/
<<<
!!Inside Templates eg: PageTemplate
{{{
<!--{{{-->
<div class="">nicely renderd and usable as a template</div>
<!--}}}-->
}}}
result:
<<<
<!--{{{-->
<div class="">nicely renderd and usable as a template</div>
<!--}}}-->
<<<
!!Different types on code blocks
{{{
<!--{{{-->
<!--}}}-->
/*{{{*/
/*}}}*/
//{{{
//}}}
}}}
and
//{{{
{{{
view the tiddler to see how it is done, without a leading space at the closing brackets :)
}}}
//}}}
TiddlyWiki for me is just a name for a wiki.
The term tiddler, has to be explaind, whenever you use it. For me "The smallest part of content in a TiddlyWiki" works best.
//{{{
config.shadowTiddlers["StyleSheetTagSearchNeuiEm"]="/*{{{*/\n"+
".tagSearch .button {\n"+
" -webkit-border-radius: 0px 15px 15px 0px;\n"+
" -moz-border-radius: 0px 15px 15px 0px;\n"+
" border-radius: 0px 15px 15px 0px;\n"+
" background-color: white;\n"+
" border: 2px 2px 2px 0 solid #ccc;\n"+
" display: block;\n"+
" margin: 0 0.2em 0.2em -0.9em;\n"+
" padding: 0 0.4em;\n"+
" font-size: 0.9em;\n"+
"}\n"+
"/*}}}*/";
store.addNotification("StyleSheetTagSearchNeuiEm",refreshStyles);
//}}}
Source: {{{<iframe height="500" width="700" src="http://www.hanovsolutions.com/trie/index.html">}}}
<html>
<iframe height="500" width="700" src="http://www.hanovsolutions.com/trie/index.html">
</html>
/***
|''Name''|TiddlySpaceSearcher|
|''Version''|0.2.5|
|''Requires''|TiddlySpaceConfig TiddlySpaceFollowingPlugin|
***/
//{{{
(function($) {
var tiddlyspace = config.extensions.tiddlyspace;
var tsScan = config.macros.tsScan;
config.shadowTiddlers.SearchTemplate = "<<view server.bag SiteIcon label:no width:24 height:24 preserveAspectRatio:yes>> <<view server.bag spaceLink title external:no>> in space <<view server.bag spaceLink>>";
config.shadowTiddlers.StyleSheetSearch = [".resultsArea .siteIcon { display: inline; }",
".searchForm {text-align: left;}"].join("\n");
store.addNotification("StyleSheetSearch", refreshStyles);
var search = config.macros.tsSearch = {
locale: {
advanced: "Advanced Options",
header: "Search",
resultsHeader: "Results (%0)",
find: "find",
noResults: "No tiddlers matched your search query",
query: "QUERY: ",
error: "please provide a search query or a tag, modifier or title!",
titleAdvanced: "where the title is",
modifierAdvanced: "where the last modifier is",
spaceAdvanced: "only in the space: ",
notspaceAdvanced: "but not in the spaces: ",
tagsAdvanced: "with the tags: "
},
andConstructor: function(container, label, fieldname, negationMode) {
var tags = $("<div />").appendTo(container);
$('<span />').text(label).appendTo(tags);
var id = "area" + Math.random();
container = $("<span />").attr("id", id).appendTo(tags)[0];
function add(container) {
var el = $('<input type="text" />').attr("field", fieldname).appendTo(container);
if(negationMode) {
el.attr("negation", "true");
}
}
add(container);
var el = $("<button />").text("AND").click(function(ev) {
add($(ev.target).data("container"));
ev.preventDefault();
}).appendTo(tags);
$(el).data("container", container);
},
fieldConstructor: function(container, label, field) {
container = $("<div />").appendTo(container)[0];
$("<span />").text(label).appendTo(container);
$("<input />").attr("text", "input").attr("field", field).appendTo(container);
},
advancedOptions: function(form) {
var locale = search.locale;
var container = $("<div />").addClass("tsAdvancedOptions").appendTo(form)[0];
$("<h2/ >").text(search.locale.advanced).appendTo(container);
$("<div />").addClass("separator").appendTo(container);
search.fieldConstructor(container, locale.titleAdvanced, "title");
search.fieldConstructor(container, locale.modifierAdvanced, "modifier");
search.fieldConstructor(container, locale.spaceAdvanced, "space");
search.andConstructor(container, locale.notspaceAdvanced, "space", true);
search.andConstructor(container, locale.tagsAdvanced, "tag");
},
constructSearchQuery: function(form) {
var data = [], select = [];
var query = $("[name=q]", form).val();
if(query) {
data.push("q=%0".format(query));
}
// add tags, fields etc..
$("[field]", form).each(function(i, el) {
var val = $(el).val();
var name = $(el).attr("field");
var negate = $(el).attr("negation") == "true";
if(val && name) {
val = encodeURIComponent(val);
val = negate ? "!" + val : val;
if(name == "space") {
val += "_public";
name = "bag";
}
if(negate) {
select.push("select=%0:%1".format(name,val));
} else {
var prefix = data.length === 0 ? "q=" : "";
data.push('%0%1:"%2"'.format(prefix, name, val));
}
}
});
var dataString = data.join(" ");
if(dataString.length === 0 && !query) {
return false;
}
var selectStatement = select.join("&");
if(dataString.length > 0 && selectStatement.length > 0) {
dataString += "&";
}
dataString += selectStatement;
return "/search?%0".format(dataString);
},
constructForm: function(place) {
var locale = search.locale;
$("<h1 />").text(locale.header).appendTo(place);
var form = $("<form />").appendTo(place)[0];
$('<input type="text" name="q" />').appendTo(form);
$('<input type="submit" />').val(locale.find).appendTo(form);
search.advancedOptions(form);
var query = $('<h2 class="query"/>').appendTo(place)[0];
var results = $("<div />").appendTo(place).addClass("resultsArea")[0];
var lookup = function(url) {
if(!url) {
results.empty().addClass("error").text(locale.error);
return;
}
config.extensions.tiddlyweb.getStatus(function(status) {
$(query).text(locale.query);
var href = status.server_host.url + url;
$("<a />").attr("href", href).text(href).appendTo(query);
tsScan.scan(results, { url: url, emptyMessage: search.locale.noResults, cache: true,
template: "SearchTemplate", sort: "title", callback: function(tiddlers) {
$("<h2 />").text(locale.resultsHeader.format(tiddlers.length)).prependTo(results);
}
});
});
};
$(form).submit(function(ev) {
ev.preventDefault();
var url = search.constructSearchQuery(form);
config.macros.tsSearch.lastSearch = url;
lookup(url);
});
if(search.lastSearch) {
lookup(search.lastSearch);
}
return form;
},
handler: function(place) {
var container = $("<div />").addClass("searchForm").appendTo(place)[0];
search.constructForm(container);
}
};
})(jQuery);
//}}}
!!Groupie knows
* [[GroupieNews|News]]@groupie
* List@groupie
* MoodOfTheDay@groupie
* GroupieNews@groupie ("subscription" see below)
* GroupieMusic@groupie (experiment)
!!!"Subscribe the ~TiddlySpace way"
* To use it, create a tiddler named ~@groupie and tag it "list"
* Write some plain text into the groupie tiddler
* In your Homespace create a menu item {{{List@groupie at groupie}}} like so:
* List@groupie at groupie
!!!"~UnSubscribe the ~TiddlySpace way"
* Just remove the "list" tag from your ~@groupie tiddler
!!!Create your own GroupieNews
* You need to be "subscribed" to groupie. See above!
* tag a tiddler {{{@groupieNews}}} in one of your spaces and GroupieNews@groupie will find it
!!!Groupie is curious
* Groupie does, what groupies do. Groupie want's to know everything.
* In your homespace create a tiddler named ''MoodOfTheDay'' and tag it {{{@groupie}}}
* Create a link {{{MoodOfTheDay@groupie}}} and you'll see, what groupie knows.
* Click: MoodOfTheDay@groupie
in reply to [[TiddlyLib: New Filter Syntax]]@bengillies ~@bengillies
<<<
The syntax would (roughly) be the following:
* #tag
* """[[Title Match]]"""
* plain text match
* ~@space/~@modifier
* [field=match]
* !not match
<<<
I don't like the syntax. It is way to complicated. For every element you have a different symbol, which may be easier to parse, but it creates issues like ~@space and ~@modifier.
I'd use {{{[field=match]}}} as the only component scheme. I think it would make the parser easier, and more extensable. I want to filter by:
[title = title with spaces]
[tag = tag with spaces]
[modifier = hugo]
[creator = hugo]
[created = >28d]
[modified = >1d]
[text = some text to find]
[space = foo]
[bag = myBag]
[recipe = someThing]
[field = match]
[UUID = ABCDEFABCDEF...]
....
NOT(...)
OR(...)
I think this is much more expressive than {{{@#\&%$,;...}}} If you need a new filter, you may run out of "hard to remember" symbols.
<<<
//{{{
ts().find('#foo [field=bar], [field=test] #bar #tag !#tag2')
//}}}
Just bear in mind that it most likely has a few bugs still in it.
<<<
I personally don't like "," as an OR expression. It is too small for me. Same with "!". I think, it makes CSS very hard to read, if there are no propper linebreaks.
//{{{
ts().find('([tag=foo] [field=bar]) OR ([field=test] [tag=bar] [tag=tag] NOT([tag=tag2]))');
//}}}
It uses more characters, but there is no problem with {{{[space = modifier] or [modifier = space] or [field = @modifier]}}}. And it should be clear for an non programmer what's going on.
Since Chris limited the the number of search results, returned by the server, I think an "OR" is not usefull anymore.
Lets say the query for {{{([tag=foo] [field=bar])}}} are the first 20 results. So there won't be any results for the right side.
Or lets say the left query are the first 100 results. The OR path will be invisible for the user.
//{{{
var left = ts().find('[tag=foo] [field=bar]');
var right = ts().find('[field=test] [tag=bar] [tag=tag] NOT([tag=tag2])');
var all = merge(all, left, right);
var found = all.find('[text=some text]');
//}}}
I need some more variables, but I think it is much clearer, what you get. And you get the first 20 results from left and from the right path, which IMO makes more sense to the user.
Grover Washington, Jr. - Winelight
|''Name:''|[[NeUIemTheme02]]|
|''Description:''|Changes the right sidebar|
|''Generator:''|[[TW FreeStyle|http://FreeStyle.tiddlyspot.com]]|
|''Gen.Description:''|Handcrafted by @pmario|
|''PageTemplate:''|NeUIemTheme##PageTemplate|
|''ViewTemplate:''|NeUIemTheme##ViewTemplate|
|''EditTemplate:''|NeUIemTheme##EditTemplate|
|''RevisionTemplate:''|NeUIemTheme##RevisionTemplate|
|''StyleSheet:''|##StyleSheet|
!StyleSheet
/*{{{*/
[[NeUIemTheme##StyleSheet]]
#sidebarTabs .tabset{
float: left;
width: 1em;
padding: 0;
}
#sidebarTabs .tabset:hover{
width: auto;
position:absolute;
right: 86%;
padding-right: 8%;
z-index: 10;
}
#sidebarTabs .tabset .tab{
overflow: hidden;
display: block;
}
/*}}}*/
! A little story in 2 parts
{{autoload{<<list filter [tag[showMeMore]]>>}}}
!SpaceUnplugged
{{unpluggedSpaceTab{
{{wizard{
<<image unsyncedIcon width:48>> Sync is currently unavailable in ~TiddlyWiki due to security constraints in modern browsers. Research is being done to build a suitable alternative. In the meantime if you have changed content in an offline ~TiddlyWiki, you can get your content back into ~TiddlySpace by using the ''import'' functionality from the backstage of the online wiki.
}}}
}}}
!Menu
<<message messages.memberStatus>> <<homeLink>>
{{unsyncedList{<<message messages.syncListHeading>> <<list filter [is[unsynced]]>>}}}
running TiddlySpace@glossary version <<message extensions.tiddlyweb.status.tiddlyspace_version>>
{{autotable{
<<tiddler Backstage##Resources>>
}}}
!Resources
[[blog|@@blog]] [[documentation|@@docs]] [[featured spaces|@@featured]]
!ImportExport
<<fileImport>>
You can download this TiddlySpace as an offline TiddlyWiki:
{{chunkyButton{<<exportSpace>>}}}
!BackstageTiddlers
|upload a <<message messages.privacySetting>> file: <<binaryUpload>>|<<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>>|
|>|<<search>>|
|>|<<tiddler Backstage##Tiddlers>>|
!Tiddlers
<<tabs
txtMainTab
"Recent" "Recently edited tiddlers" TabTimeline
"All" "All tiddlers" TabAll
"Public" "All public tiddlers" [[TiddlySpaceTabs##Public]]
"Private" "All private tiddlers" [[TiddlySpaceTabs##Private]]
"Tags" "All tags" TabTags
"Spaces" "Tiddlers grouped by space" [[TiddlySpaceTabs##Spaces]]
"Missing" "Missing tiddlers" TabMoreMissing
"Orphans" "Orphaned tiddlers" TabMoreOrphans
"Shadows" "Shadowed tiddlers" TabMoreShadowed
>>
!BatchOps
<<tabs
txtPublisherTab
"Private" "Move tiddlers from private to public" Backstage##BatchPrivate
"Public" "Move tiddlers from public to private" Backstage##BatchPublic
>>
!BatchPrivate
<<TiddlySpacePublisher type:private>>
!BatchPublic
<<TiddlySpacePublisher type:public>>
!Plugins
''Note:'' Many of these plugins are core TiddlySpace plugins and cannot be changed unless first cloned.
<<tiddler PluginManager>>
!Tweaks
These options change behavior in TiddlyWiki //only// and may be ineffective in TiddlySpace.
<<tiddler AdvancedOptions>>
/***
|Name:|SelectThemePluginMP|
|Description:|Lets you easily switch theme and palette|
|Version:|1.0.1 ($Rev: 3646 $) MP 03 (2011.06.26)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|OriginalSource:|http://mptw.tiddlyspot.com/#SelectThemePlugin|
|OriginalAuthor:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
|Author:|Mario Pietsch|
!Notes
* Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin
* Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example)
* Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware.
*MP Added the label to applyTheme macro.
*Made selectPalette tiddlySpace ready.
!Usage
* {{{<<selectTheme>>}}} makes a dropdown selector
* {{{<<selectPalette>>}}} makes a dropdown selector
* {{{<<applyTheme>>}}} applies the current tiddler as a theme
* {{{<<applyPalette>>}}} applies the current tiddler as a palette
* {{{<<applyTheme TiddlerName>>}}} applies TiddlerName as a theme
* {{{<<applyPalette TiddlerName>>}}} applies TiddlerName as a palette
* {{{<<applyTheme TiddlerName label>>}}} applies TiddlerName as a theme and uses costumized button label
* {{{<<applyTheme {{tiddler.title}} label>>}}} applies actual tiddler as a theme and uses costumized button label
***/
//{{{
config.macros.selectTheme = {
label: {
selectTheme:"select theme",
selectPalette:"select palette"
},
prompt: {
selectTheme:"Select the current theme",
selectPalette:"Select the current palette"
},
tags: {
selectTheme:'systemTheme',
selectPalette:'systemPalette'
}
};
config.macros.selectTheme.handler = function(place,macroName)
{
var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick);
// want to handle palettes and themes with same code. use mode attribute to distinguish
btn.setAttribute('mode',macroName);
};
config.macros.selectTheme.onClick = function(ev)
{
var e = ev ? ev : window.event;
var popup = Popup.create(this);
var mode = this.getAttribute('mode');
var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]);
// for default
if (mode == "selectPalette") {
var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',"(default)");
btn.setAttribute('mode',mode);
}
for(var i=0; i<tiddlers.length; i++) {
var t = tiddlers[i].title;
var name = store.getTiddlerSlice(t,'Name');
var desc = store.getTiddlerSlice(t,'Description');
var btn = createTiddlyButton(createTiddlyElement(popup,'li'), name?name:t, desc?desc:config.macros.selectTheme.label['mode'], config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',t);
btn.setAttribute('mode',mode);
}
Popup.show();
return stopEvent(e);
};
config.macros.selectTheme.onClickTheme = function(ev)
{
var mode = this.getAttribute('mode');
var theme = this.getAttribute('theme');
if (mode == 'selectTheme')
story.switchTheme(theme);
else // selectPalette
config.macros.selectTheme.updatePalette(theme);
return false;
};
config.macros.selectTheme.updatePalette = function(title)
{
var tiddlyspace = config.extensions.tiddlyspace;
var co = config.options;
if (title != "") {
if (!tiddlyspace && (title != "(default)")) {
store.deleteTiddler("ColorPalette");
store.saveTiddler("ColorPalette","ColorPalette",store.getTiddlerText(title),
config.options.txtUserName,undefined,"");
}
else if (tiddlyspace && (title != "(default)")) {
var tiddler = store.getTiddler('ColorPalette');
var bag = tiddler.fields["server.bag"];
var cs = tiddlyspace.currentSpace.name;
if ( (bag != cs+"_private") && (bag != cs+"_public") ) {
tiddler.fields["server.workspace"] = (co.chkPrivateMode) ? "bags/%0_private".format([cs]) : "bags/%0_public".format([cs]);
// remove all tags eg: "excludeLists, ..Search "
tiddler.tags = [];
}
tiddler.fields["server.page.revision"] = "false"; // hacky
delete tiddler.fields["server.permissions"];
delete tiddler.fields["server.title"];
delete tiddler.fields["server.etag"];
store.saveTiddler("ColorPalette","ColorPalette", store.getTiddlerText(title),
config.options.txtUserName,undefined,tiddler.tags, tiddler.fields);
}
refreshAll();
if(config.options.chkAutoSave) {
saveChanges(true);
}
} // if (title != "")
};
config.macros.applyTheme = {
label: "apply",
prompt: "apply this theme or palette: " // i'm lazy
};
config.macros.applyTheme.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
var label = params[1] ? params[1] : this.label;
var useTiddler = params[0] ? params[0] : tiddler.title;
var btn = createTiddlyButton(place,label,this.prompt+useTiddler,config.macros.selectTheme.onClickTheme);
btn.setAttribute('theme',useTiddler);
btn.setAttribute('mode',macroName=="applyTheme"?"selectTheme":"selectPalette"); // a bit untidy here
}
config.macros.selectPalette = config.macros.selectTheme;
config.macros.applyPalette = config.macros.applyTheme;
config.macros.refreshAll = { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
createTiddlyButton(place,"refresh","refresh layout and styles",function() { refreshAll(); });
}};
//}}}
/***
|''Name''|TiddlySpaceRevertRevision|
|''Description''|Revert to a previous revision|
|''Author''|BenGillies|
|''Version''|0.1|
|''Status''|unstable|
|''Source''|http://github.com/TiddlySpace/tiddlyspace|
|''CodeRepository''|http://github.com/TiddlySpace/tiddlyspace|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.6.0|
|''Requires''|TiddlyWebAdaptor TiddlySpaceRevisionView|
!Usage
Add a control button to revert to a particular revision.
The button must be called from within a revision, as generated by TiddlySpaceRevisionView
!Code
***/
//{{{
(function($) {
config.commands.revert = {
text: "revert",
tooltip: "make this revision the current one",
handler: function(ev, src, title) {
var revElem = story.getTiddler(title);
var tidToRevert = store.getTiddler($(revElem).attr("revName"));
var revision = store.getTiddler(title);
if ((revision) && (tidToRevert)) {
tidToRevert.text = revision.text;
var newFields = merge({}, revision.fields);
for (var fieldName in newFields) {
if (fieldName.substr(0, 7) === "server.") {
delete newFields[fieldName];
}
}
merge(tidToRevert.fields, newFields);
tidToRevert.tags = merge([], revision.tags);
tidToRevert.fields.changecount = 1;
delete tidToRevert.fields.doNotSave;
store.saveTiddler(tidToRevert.title, tidToRevert.title,
tidToRevert.text, null, null, tidToRevert.tags,
tidToRevert.fields, false, tidToRevert.created, tidToRevert.creator);
autoSaveChanges(true);
}
}
};
})(jQuery);
//}}}
<!DOCTYPE HTML>
<html>
<body style="display:none">
topics: <ul id="topics"></ul>
<button id='addtopic'>add topic</button>
stream:
<ul id="stream"></ul>
<script type='text/javascript' src='/bags/common/tiddlers/jquery.js'></script>
<script type='text/javascript' src='/bags/tiddlyspace/tiddlers/chrjs'></script>
<script src="/twikifier.js" type="text/javascript" charset="utf-8"></script>
<script type='text/javascript'>
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView", "false");
}
});
function renderTopic(topic) {
var item = $("<li />").appendTo("#topics");
$("<button class='show' />").text(topic).appendTo(item);
$("<button class='delete'>x</button>").appendTo(item);
return item[0];
}
var host = '/';
var space = "jon";
var active_topics = [];
var current_topic, offset;
function renderTopics() {
var topics = active_topics;
$("#topics").empty();
for(var i = 0; i < topics.length; i++) {
var topic = topics[i];
if(topic) {
renderTopic(topic);
}
}
$("body").show();
}
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var topicList = new tiddlyweb.Tiddler("Topics", new tiddlyweb.Bag(space + "_public", host));
topicList.get(function(tid) {
active_topics = tid.text.split("\n");
renderTopics(active_topics);
$("#topics .show:first").trigger("click");
},
function() {
active_topics = ["tiddlyspace"];
renderTopics(active_topics)
}
);
$("#addtopic").click(function(ev) {
var text = prompt("What topic would you like to watch?");
if(active_topics.indexOf(text) === -1) {
active_topics.push(text);
}
var el = renderTopic(text);
topicList.text = active_topics.join("\n");
topicList.put(function() {
$("button.show", el).trigger("click");
}, function() {
alert("eek!")
});
});
$("#topics .delete").live("click",function(ev) {
var topic = $(".show", this.parentNode).text();
active_topics.remove(active_topics.indexOf(topic));
renderTopics();
topicList.text = active_topics.join("\n");
topicList.put(function() {}, function() {
alert("eek!")
});
});
w = createWikifier(window, jQuery, { host: host, container: "recipes/" + space + "_public" });
$("#topics .show").live("click",function(ev) {
var tag = $(this).text();
current_topic = tag;
offset = 0;
$("#stream").empty();
var search = new tiddlyweb.Search('tag:"' + tag + '" &fat=y', host);
search.get(function(tiddlers) {
for(var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var item = $("<li />").appendTo("#stream")[0];
$("<h2 />").text(tiddler.title + ": ").appendTo(item);
$("<div class='text' />").text(tiddler.text).appendTo(item);
$("<div class='author' />").text(tiddler.modifier).appendTo(item);
}
}, function() {
$("<li>no topics :-(</li>").appendTo("#stream");
});
});
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()) {
offset += 10;
// find a way to get all tiddlers created before the ones above
console.log("loadMore();");
}
});
</script>
</body>
</html>
/***
|''Name''|ImportExternalLinksPlugin|
|''Author''|Jon Robson|
|''Version''|0.3.0|
|''Requires''|TiddlySpaceConfig TiddlySpaceLinkPlugin TiddlySpaceCloneCommand|
|''Description''|Turns space links into ajax links so you don't have to leave the comfort of your own TiddlyWiki|
!Notes
This maybe should hides the editTiddler, cloneTiddler commands. Ideally the toolbar commands should hide themselves but we need a strong concept of "this is a sucked in tiddler" to do that.
***/
//{{{
(function($){
var tiddlyspace = config.extensions.tiddlyspace;
_createSpaceLink = createSpaceLink;
if(_createSpaceLink) {
createSpaceLink = function(place, spaceName, title, alt, isBag) {
var tooltip = "Click to open in current document. Right click to open in original space.";
_createSpaceLink(place, spaceName, title, alt, isBag);
var workspace;
if(isBag) {
workspace = "bags/%0".format(spaceName);
} else {
workspace = "bags/%0_public".format(spaceName);
}
if(title && spaceName != tiddlyspace.currentSpace.name) {
var link = $("a:last", place);
var newlink = $("<a />").text("[link]").after(link[0]);
// very hacky
var updateInterval = setInterval(function() {
var href = link.attr("href");
if(href) {
$(newlink).attr("href", href);
clearInterval(updateInterval);
}
}, 200);
if(link.parent(".replyLink").length == 0) { // don't suck in a reply link.
link.attr("title", tooltip).addClass("importLink").click(function(ev) {
if(config.floorboards) {
config.floorboards.pushUnique("%0_public".format(spaceName));
}
tiddlyspace.displayServerTiddler(ev.target, title, workspace, function(el) {
// TODO: the commands should disable themselves based on the meta information.
//$("[commandname=editTiddler], [commandname=cloneTiddler]", el).hide();
});
ev.preventDefault();
});
}
}
};
}
var _cloneHandler = config.commands.cloneTiddler.handler;
config.commands.cloneTiddler.handler = function(event, src, title) {
var _tiddler = store.getTiddler(title);
var source = _tiddler ? _tiddler.fields["server.bag"] : false;
var imported = _tiddler ? _tiddler.fields["tiddler.source"] : false;
var realTitle = _tiddler ? _tiddler.fields["server.title"] : title;
_cloneHandler.apply(this, [event, src, title]);
var tidEl = story.getTiddler(title);
$(story.getTiddlerField(title, "title")).val(realTitle);
if(source) {
$("<input />").attr("type", "hidden").attr("edit", "tiddler.source").val(source).appendTo(tidEl);
$("<input />").attr("type", "hidden").attr("edit", "server.activity").appendTo(tidEl);
}
}
})(jQuery);
//}}}
Once you have some content then you may choose to determine a tiddler, or set of tiddlers to display each time you load ~TiddlySpace. This is determined by the [[DefaultTiddlers]].
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>This Space</title>
<link href="/bags/common/tiddlers/profile.css" type='text/css' rel='stylesheet' >
<link href="/bags/common/tiddlers/admin.css" type='text/css' rel='stylesheet' >
</head>
<body>
<div id="container">
<div id="text-html" class="main section">
<a class="app" href="/">home</a>
<div class="left">
<h2>About this space <button class='toggleNext'></button></h2>
<div id="siteinfo"></div>
<h2>Site Icon</h2>
<div>
<img id="siteicon" class="siteicon">
<form id="upload" method="POST" enctype="multipart/form-data">
<input type="hidden" name="title" value="SiteIcon" />
<input type="hidden" name="tags" value="excludeLists">
<input type="hidden" name="csrf_token" class="csrf" />
<input type="file" name="file" accept="image/*" />
<input class="btn" type="submit" value="upload" />
</form>
<div id="dropzone">Drop file here
<img class="notloading" src="/bags/common/tiddlers/ajax-loader.gif" alt="submitting SiteIcon" />
</div>
</div>
<h2>Vital Statistics</h2>
<div id="info">please wait while information is loaded about this space...</div>
</div>
<div class="right">
<div class="ts-membership">
<h2>
Add Member
<a href="http://docs.tiddlyspace.com/What%20is%20a%20member%3F" title="What is a Member?" class="help">What is a Member?</a>
</h2>
<div>
<p>Add a new member to your space by entering their name below. Enter a space name instead and prefix with @ to add everyone who is already a member of that space.</p>
<form class="ts-members">
<input class="inputBox" type="text" name="username">
<input type="submit" value="Add Member" class="btn" />
</form>
</div>
<h2>
Existing Members <button class='toggleNext'></button>
</h2>
<div>
Your space currently has the following members:
<ul class="ts-members"></ul>
</div>
<h2>
Include Space
<a class="help" href="http://docs.tiddlyspace.com/What%20is%20space%20inclusion%3F" title="What is inclusion?">What is Inclusion?</a>
</h2>
<form class="ts-includes">
<input class="inputBox" type="text" name="spacename">
<input type="submit" value="Include Space" class="btn" />
</form>
</div>
<div>
<h2>Included Spaces <button class='toggleNext'></button></h2>
<div>
This space includes the following spaces:
<ul class="ts-includes"></ul>
</div>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<script src='/bags/common/tiddlers/backstage.js'></script>
<script src='/bags/common/tiddlers/jquery.js'></script>
<script src='/bags/tiddlyspace/tiddlers/chrjs'></script>
<script src='/bags/common/tiddlers/chrjs.space'></script>
<script src='/bags/common/tiddlers/chrjs.users'></script>
<script src='/bags/common/tiddlers/chrjs.identities'></script>
<script src='/bags/tiddlyspace/tiddlers/TiddlySpaceCSRF'></script>
<script src='/bags/common/tiddlers/jquery-form.js'></script>
<script src="/bags/common/tiddlers/siteiconupload.js"></script>
<script src="/bags/common/tiddlers/ts.js"></script>
<script src="/status.js"></script>
<script src="/bags/common/tiddlers/space.js"></script>
<!--[if lt IE 8]>
<script type="text/javascript" src="/bags/common/tiddlers/json2.js"></script>
<![endif]-->
</body>
</html>
/*{{{*/
Background: #f3f0e1
Foreground: #1d1a0b
PrimaryPale: #fcfbf7
PrimaryLight: #d9ce9d
PrimaryMid: #b49f45
PrimaryDark: #000000
SecondaryPale: #faf7fc
SecondaryLight: #c39dd9
SecondaryMid: #8b45b4
SecondaryDark: #000000
TertiaryPale: #f7fcfc
TertiaryLight: #9dd9d9
TertiaryMid: #45b4b4
TertiaryDark: #000000
/*}}}*/
At the moment the "following" bubble top left at my tiddlers, indicates if someone I follow, hosts a tiddler with the same name. I like this behaviour, because it gives me a summary of opinions I care of.
On the other hand, there is the new [[linksocial]]@linksocial plugin from @jon, which links to tiddlers that mention/link to my tiddlers. Even if I don't follow them and tiddler names may be different (~@jon right?). This info is quite interesting too, because it offers the oportunity to meet new interesting people.
Mailboxes@espace ~@espace suggests a ~TiddlySpace internal mailing system.
Which is an interesting idea, if we could solve it the ''~TiddlySpace way''.
----
cdent says at: [[Mailboxes]]@cdent
<<<
Yeah, I think maybe we should turn on linksocial in general.
<<<
Introducing this space to a broader audience or even include it into the default space would be nice. See [[A Journey Contacting New Members]]@pmario
[[Replies and Notifications]]
<<activity>>
In reply to bengillies [[The Sync mechanism and april1111]]@bengillies
<<<
We should discuss the UI of the upcoming sync mechanism, i.e. how exactly do we want it to work?
Seemlessly in the background?
<<<
* If I work offline, having an active internet connection.
** Nothing should be done automatically.
** I downloaded the file to work offline. If I want to sync I'll tell.
* Notification ''Yes''. I like it, to know what's going on.
* Working online
* I am ok, if the default settings, helps the user as much as needed.
** As long, as I can switch automatic "helping" off.
** I am a control freak about this.
* Notification: Yes
<<<
...
Every time a user saves a tiddler? How do we want to deal with things like conflicts (and not just edit conflicts, i.e. if a tiddler is on screen, the user might be reading it, so that's a conflict. How do we deal with that)?
<<<
* I like the info/feedback/notification in some chat programs, where you can see, if the other side types something. I think about a little animated pen, getting visible at the header of the tiddler, that indicated, that someone has changed this tiddler on the server.
Provides configuration for TagSearchPlugin...
!Tags
[[Priority]]
[[Action]]
[[Project]]
[[Contact]]
[[Many]]
!More
[[TAG:Archive]]
[[Journal]]
[[Reference]]
[[systemConfig]]
[[systemConfigDisable]]
[[excludeMissing]]
[[excludeSearch]]
[[excludeLists]]
[[TagSearchLegacy]]
|uiDefault|Verdana,Arial,sans-serif|
|uiEditor|Verdana,Arial,sans-serif|
|twDefault|Arial, 'Linux Biolinum O', helvetica|
|twEditor|Inconsolata|
|twTitle|'Trebuchet MS' sans-serif|
|twHeader|'Trebuchet MS' sans-serif|
|navDefault|Inconsolata|
/***
|''Name''|tsScanCountPlugin|
|''Description''|Provides ability to count tiddlers at a given tiddlyspace url and display a button that when clicked lists them. Also upgrades tsScan to replace any options containing with $1 with the current space|
|''Version''|0.2.0|
***/
//{{{
(function($) {
var tsScan = config.macros.tsScan;
var tiddlyspace = config.extensions.tiddlyspace;
var macro = config.macros.tsScanCount = {
cache: true,
countCache: {},
handler: function(place, macroName, params, w, paramString, tiddler) {
var container = $("<a href='#' class='button' />").attr("refresh", "macro").attr("macroName", macroName).appendTo(place)[0];
$(container).data("params", paramString);
macro.refresh(container);
},
refresh: function(container) {
var paramString = $(container).data("params");
var options = tsScan.getOptions(paramString, tiddler);
var url = options.url;
options.cache = macro.cache;
options.callback = function(tiddlers) {
options.cache = true;
macro.cache = true;
var count = tiddlers[0] ? tiddlers[0].fields['server.page.revision'] : 0;
var lastCount = macro.countCache[url] || 0;
if(lastCount != count) {
var interval, step = 0;
interval = window.setInterval(function() {
var last = step;
step += 1;
$(container).removeClass("step" + last);
if(step > 10) {
macro.countCache[url] = count;
window.clearInterval(interval);
} else {
$(container).addClass("step" + step);
}
}, 500)
}
$(container).empty().addClass("enabled").text(tiddlers.length).click(function(ev) {
$(ev.target).addClass("active");
var target = options.popupSelector ? $(options.popupSelector)[0] : ev.target;
var p = Popup.create(target, "div");
var container;
if(options.heading) {
container = $("<div />").addClass("heading").appendTo(p)[0];
wikify(store.getTiddlerText(options.heading) || "", container);
}
container = $("<div />").addClass("followTiddlersList").appendTo(p)[0];
tsScan.scan(container, options);
Popup.show();
ev.stopPropagation();
return false;
});
};
tsScan.scan(container, options);
}
}
var _getOptions = tsScan.getOptions;
config.macros.tsScan.getOptions = function(paramString, tiddler) {
var options = _getOptions.apply(this, arguments);
var optionsClone = {};
for(var i in options) {
if(typeof(options[i]) == "string") {
optionsClone[i] = options[i].format(tiddlyspace.currentSpace.name);
} else {
optionsClone[i] = options[i];
}
}
return optionsClone;
}
// every 5 minutes make tsScan update.
window.setInterval(function() {
macro.cache = false;
$("[macroName=tsScanCount]").each(function(i, el) {
macro.refresh(el);
});
}, 1000 * 60 * 5);
})(jQuery);
//}}}
@pennys-icons has real nice stuff. But two things are missing. Where does it come from, and what license is it? Is it allowed to take some of the symbols?
in reply to @jon:
*I vote for an additional parameter. eg: {{{button:buttonText}}} which would look like {{{<<followTiddlers button:'?'>>}}}
!Others say
<<tsScan [[Delay following search]] fat:y template:"TEMPLATES##scan" query:"select=modifier:!pmario">>
/***
|''Name''|TiddlySpaceCloneCommand|
|''Version''|0.5.8|
|''Description''|provides a toolbar command for cloning external tiddlers|
|''Status''|stable|
|''Source''|http://github.com/TiddlySpace/tiddlyspace/raw/master/src/plugins/TiddlySpaceCloneCommand.js|
|''Requires''|TiddlySpaceConfig TiddlySpaceFilters|
!Code
***/
//{{{
(function($) {
var cmd = config.commands;
var tiddlyspace = config.extensions.tiddlyspace;
var fieldsCache = {};
cmd.cloneTiddler = {
text: cmd.editTiddler.text,
tooltip: "Create a copy of this tiddler in the current space",
errorMsg: "Error publishing %0: %1",
isEnabled: function(tiddler) {
return !config.filterHelpers.is.local(tiddler) && !readOnly;
},
handler: function(ev, src, title) {
var tiddler = store.getTiddler(title);
if(tiddler) {
fieldsCache[title] = $.extend({}, tiddler.fields);
tiddler.fields["server.workspace"] = tiddlyspace.getCurrentWorkspace(config.options.chkPrivateMode ?
"private" : "public");
tiddler.fields["server.permissions"] = "read, write, create"; // no delete
delete tiddler.fields["server.page.revision"];
delete tiddler.fields["server.title"];
delete tiddler.fields["server.etag"];
// special handling for pseudo-shadow tiddlers
if(tiddlyspace.coreBags.contains(tiddler.fields["server.bag"])) {
tiddler.tags.remove("excludeLists");
}
} else { // ensure workspace is the current space
var el = story.findContainingTiddler(src);
el = $(el);
var fields = el.attr("tiddlyfields");
if(fields) { // inherited via TiddlyLink
fields = fields.decodeHashMap();
fields["server.workspace"] = config.
defaultCustomFields["server.workspace"];
} else {
fields = config.defaultCustomFields;
}
fields = String.encodeHashMap(fields);
el.attr("tiddlyfields", fields);
}
cmd.editTiddler.handler.apply(this, arguments);
if(tiddler) {
tiddler.fields["server.permissions"] += ", delete";
}
return false;
}
};
cmd.editTiddler.isEnabled = function(tiddler) {
return !cmd.cloneTiddler.isEnabled.apply(this, arguments);
};
// hijack cancelTiddler to restore original fields
var _cancelHandler = cmd.cancelTiddler.handler;
cmd.cancelTiddler.handler = function(ev, src, title) {
var tiddler = store.getTiddler(title);
if(tiddler) {
tiddler.fields = fieldsCache[title] || tiddler.fields;
delete fieldsCache[title];
}
return _cancelHandler.apply(this, arguments);
};
// hijack saveTiddler to clear unused fields stash
var _saveHandler = cmd.saveTiddler.handler;
cmd.saveTiddler.handler = function(ev, src, title) {
delete fieldsCache[title];
return _saveHandler.apply(this, arguments);
};
})(jQuery);
//}}}
<<tiddler FollowTemplate>>
<<tabs
txtMainTab
"Latest" "Latest edited tiddlers (short list)" TimelineShort
"Recent" "Recently edited tiddlers" TabTimeline
"All" "All tiddlers" TabAll
"Public" "All public tiddlers" [[TiddlySpaceTabs##Public]]
"Private" "All private tiddlers" [[TiddlySpaceTabs##Private]]
"Tags" "All tags" TabTags
"Spaces" "Tiddlers grouped by space" [[TiddlySpaceTabs##Spaces]]
"Following" "People you are following" TabFollowing##Following
"Followers" "People who are following you" TabFollowing##Followers
"Missing" "Missing tiddlers" TabMoreMissing
"Orphans" "Orphaned tiddlers" TabMoreOrphans
"Shadows" "Shadowed tiddlers" TabMoreShadowed
>>
/% If you want to have the default back, just activate the following line
<<tiddler Backstage##Tiddlers>>%/
/***
|''Name''|RefreshTiddlerCommand|
|''Version''|0.3.0|
***/
//{{{
(function($) {
var cmd = config.commands.refreshTiddler = {
text: "refresh",
locale: {
refreshing: "Refreshing tiddler..."
},
tooltip: "refresh this tiddler to be the one on the server",
handler: function(ev, src, title) {
var tiddler = store.getTiddler(title);
if(!tiddler) {
tiddler = new Tiddler(title);
merge(tiddler.fields, config.defaultCustomFields);
}
$(story.getTiddler(title)).find(".viewer").
empty().text(cmd.locale.refreshing);
var dirtyStatus = store.isDirty();
story.loadMissingTiddler(title, {
"server.workspace": tiddler.fields["server.recipe"] ? "recipes/" + tiddler.fields["server.recipe"] :
tiddler.fields["server.workspace"] || "bags/"+tiddler.fields["server.bag"],
"server.host": tiddler.fields["server.host"],
"server.type": tiddler.fields["server.type"]
}, function() {
store.setDirty(dirtyStatus);
});
}
};
})(jQuery);
//}}}
/***
|''Name''|ExtraKeysAddOn|
|''Description''|This AddOn contains the extra key handling for zCodeMirrorPlugin|
|''Author''|PMario|
|''Version''|0.1.3|
|''Status''|''beta''|
|''Source''|http://codemirror-plugins.tiddlyspace.com/#RenderBuffer.js|
|''License''|[[CC by-nc-sa 3.0|http://creativecommons.org/licenses/by-nc-sa/3.0/]]|
|''CoreVersion''|2.5.0|
|''Keywords''|TAB key handling |
! Documentation
<<<
This addOn needs to be used together with [[zCodeMirrorPlugin]]. It contains:
* simpleTab
** If TAB key is pressed, it just inserts a tab.
** If some text is selected the text will be deleted and a tab will be inserted.
* smartTab
** If no text is selected it inserts a tab.
** If some text or some lines are selected the selected lines will be indented by one tab.
** If text is selected <shift><tab> will unindent the selected lines. This behaviour is preferred, for programming.
* Using {{{simpleTab}}} or {{{smartTab}}} can be configured at CodeMirrorConfig tiddler.
** Default is .. {{{ extraKeys: smartTab }}}
* <F11> key toggles the editor height.
<<<
! Important
<<<
The option {{{chkInsertTabs}}} needs to be ''unchecked'' to use {{{smartTab}}} handling.
<<option chkInsertTabs>> {{{chkInsertTabs}}} Use the tab key to insert tab characters instead of moving between fields.
<<<
! History
<<<
* V 0.1.3 2012-06-33
** Updated "shift-tab" handling for "smartTab" mode.
* V 0.1.2 2012-03-13
** Added functions to make editor height persistent.
** + bug fixes introduce with V 0.1.1
<<<
***/
//{{{
version.extensions.ExtraKeyAddOns = {
major: 0,
minor: 0,
revision: 1,
date: new Date(2012, 6, 23)
};
// Returns the specified field (input or textarea element) in a tiddler
// or null if it found no field
Story.prototype.hasTiddlerField = function(title,field)
{
var tiddlerElem = this.getTiddler(title);
var e = null;
if(tiddlerElem) {
var t,children = tiddlerElem.getElementsByTagName("*");
for(t=0; t<children.length; t++) {
var c = children[t];
if(c.tagName.toLowerCase() == "input" || c.tagName.toLowerCase() == "textarea") {
if(c.getAttribute("edit") == field)
e = c;
}
}
}
return e;
};
if (!config.tools) config.tools = {};
if (!config.tools.cm) config.tools.cm = {};
if (!config.tools.cm.addOns) config.tools.cm.addOns = {};
(function ($) {
var me;
config.tools.cm.addOns.toggleMaxHeight = me = {
F11: function (ed) {
var oldHeight,
$scroll,
tidEl = story.findContainingTiddler(ed.getWrapperElement()),
cmHeight,
corr = 25; // TODO make configurable
$scroll = $(ed.getScrollerElement());
oH = $scroll.data('oldHeight');
if (!oH || oH == $scroll.height()) {
$scroll.data('oldHeight', $scroll.height());
$scroll.height(config.tools.cm.guessMaxHeight(corr));
window.scrollTo(0,ensureVisible(ed.getScrollerElement())+1); // +1 sucks but I want to see the border!
cmHeight = 'max';
}
else {
window.scrollTo(0,ensureVisible(ed.getScrollerElement())-1); // -1 sucks
$scroll.height(oH);
cmHeight = 'min';
}
var title = tidEl.getAttribute('tiddler');
var f = story.hasTiddlerField(title,'cm.height');
if (!f ) {
story.addCustomFields(tidEl, 'cm.height:'+cmHeight);
}
else {
f.setAttribute('value', cmHeight);
}
ed.refresh();
}
},
// smartTab
// if _no_ text is selected, it inserts a tab char
// if text is selected, it indents the selected block
config.tools.cm.addOns.smartTab = {
"Shift-Tab": function (instance) {
CodeMirror.commands.indentLess(instance);
},
"Tab": function (instance) {
if (instance.somethingSelected())
CodeMirror.commands.indentMore(instance);
else
CodeMirror.commands.insertTab(instance);
}
}, // end plugin
// simpleTab
// if _no_ text is selected, it inserts a tab char
// if text is selected, it _deletes_ the selected block and inserts a tab char
config.tools.cm.addOns.simpleTab = {
Tab: "insertTab"
}
})(jQuery);
//}}}
/*{{{*/
[[codemirror.css]]
[[tiddlywiki.css]]
.CodeMirror {
border: 1px solid [[ColorPalette::PrimaryMid]];
background: [[ColorPalette::PrimaryPale]];
}
/*}}}*/
This space lets you see who is including any space.
<<inclusionLookup>>
<<inclusionCount inclusion suffix:"space(s) are including this space.">>
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
/***
|''Name''|RandomSpacePlugin|
|''Description''|To aid space discovery in TiddlySpace|
|''Requires''|TiddlySpaceConfig ImageMacroPlugin|
|''Version''|0.7.0|
!StyleSheet
.randomSpace {
width: 20em;
text-align: center;
}
.randomSpace .siteIcon, .randomSpace .label, .randomSpace .description {
text-align: center;
display: block;
}
.randomSpace .description {
border: solid 1px black;
}
.randomSpace .anotherLink {
}
***/
//{{{
(function($) {
var tiddler = {title: "RandomSpacePlugin"};
var name = "StyleSheetRandomSpace";
config.shadowTiddlers[name] = store.getTiddlerText(tiddler.title +
"##StyleSheet");
store.addNotification(name, refreshStyles);
var tweb = config.extensions.tiddlyweb;
var tiddlyspace = config.extensions.tiddlyspace;
var imageMacro = config.macros.image;
var macro = config.macros.RandomSpace = {
_cache: [],
_cacheSiteInfo: {},
handler: function(place, macroName, params) {
var options = {
limit: params[0] || 1
};
macro.renderRandomSpace(place, options);
},
chooseSpaceAndRender: function(place, options) {
$(place).empty();
var tiddlers = macro._cache;
var i = macro.randomIndex(tiddlers);
var tiddler = tiddlers[i];
var bag = tiddler.bag;
macro.renderSiteInfo(place, bag, options);
},
renderRandomSpace: function(place, options) {
var container = $("<div />").addClass("randomSpace").text("please wait... ").appendTo(place)[0];
var limit = options.limit;
if(macro._cache.length > 0) {
macro.chooseSpaceAndRender(container, options);
} else {
ajaxReq({
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView", "false");
},
url:"/search?q=title:SiteInfo",
success: function(tiddlers) {
var cache = [];
for(var i=0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
if(tiddler.bag.indexOf("_private") == -1) {
cache.push(tiddler);
}
}
macro._cache = cache;
macro.chooseSpaceAndRender(container, options);
},
error: function() {
$(container).empty();
}
});
}
},
renderSiteInfo: function(place, bag, options) {
var container = $("<div class='space' />").appendTo(place);
var space = bag.replace("_public", "");
tweb.getStatus(function(status) {
var host = status.server_host;
var avatar = tiddlyspace.getAvatar(host, { name: space });
var image = $("<div class='siteIcon' />").appendTo(container);
imageMacro.renderImage(image, avatar, { width:48, height: 48 });
var url = tiddlyspace.getHost(host, space);
$("<a />").addClass("label").attr("href", url).text(space).appendTo(container);
var info = $('<div class="description" />').text("loading info... ").appendTo(container);
if(macro._cacheSiteInfo[bag]) {
var tiddler = macro._cacheSiteInfo[bag];
info.empty();
wikify(tiddler.text, info[0]);
} else {
ajaxReq({
url: "/bags/%0/tiddlers/SiteInfo".format([bag]),
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-ControlView", "false");
},
success: function(tiddler) {
info.empty();
macro._cacheSiteInfo[bag] = tiddler;
wikify(tiddler.text, info[0]);
}
});
}
$("<a />").addClass("anotherLink").attr("href", "javascript:;").text("click for another").click(function(ev) {
$(place).empty();
macro.renderRandomSpace(place, options);
}).appendTo(container);
});
},
randomIndex: function(list) {
return Math.round((list.length - 1) * Math.random());
}
}
})(jQuery);
//}}}
2011-07-02
In his second Update [[TiddlyLib Wikitext]]@bengillies ~@bengillies points out, that he could think of transclusions with parameters like so:
<<<
{{{
<<My tiddler widget##param1¶m2>>
}}}
Where everything after the ## would be (as happens now) not part of the tiddler name, but would be passed in to mean sub-tiddler (or at least, a specific part of the tiddler).
If the tiddler being transcluded is wikitext, then it could transclude just that section; if it's HTML + javascript, then it could take advantage of the parameters to alter it's output.
I still haven't thought through exactly how that would work in practise, but I do like the idea.
<<<
''I like this idea.''
What I don't like is, that it contains unnamed params. First of all they are most of the time not "speaking" and they are order dependent.
I vote for "named params only". eg:
{{{
<<My tiddler widget##"tag":"holidayPlanning"; "outputHeading":"The ultimate holiday">>
}}}
* These parameters would be easy to parse. Just throw them into a JSON parser, with some pre- and post-fixes.
* There is still the problem: "How do I, as a user dynamically create named params"?<br>eg: The output/result from one transclusion should be the input to the next one :) Something similar to unix pipes.
** Which will come in handy, if I want to create tiddler reports.
----
2011-06-30
in reply to [[TiddlyLib Wikitext]]@bengillies ~@bengillies Update
<<<
This leaves us with the following:
Say you want to create a report thing inside a tiddler that you'd normally use a macro for. You get a report thing that you want; put it into a tiddler; go to the tiddler you want it to appear in; transclude it. This also means that said report-thing tiddler woud work perfectly well opened up by itself too. This should (hopefully) help keep things tweakable and extensible, whilst still keeping things nicely separate.
<<<
That's nice. So I have the "report-ting tiddler" that works stand alone, and as a transclusion.
Nice.
But now I want to use this "template" tiddler a second time, but this time, I don't want to display tiddlers tagged "lastHoliday", I want to display tiddlers tagged:"holidayPlanning".
Since I invested allready 4 hours developing the template, I simply want to reuse it. eg: {{{<<report-thing tag:holidayPlanning>>}}}. Creating a new "report-thing" tiddler, where only one filter word is different is waste of time.
It would be acceptable, if there are only two "report-ting" tiddlers that are allmost the same. But what, if I have 3 :) Keeping things up to date wouldn't be nice.
----
in reply to [[TiddlyLib Wikitext]]@bengillies ~@bengillies
<<<
For the wikitext, for now, I'm proposing the following changes:
* no more {{{@@}}} inline CSS stuff
* no more inline HTML fragments
<<<
+1
<<<
* no more inline macros
<<<
-1 See my [[TiddlyLib Motivations]]@pmario
<<<
* we change transclusion syntax from {{{<<tiddler TiddlerName>>}}} to {{{<<TiddlerName>>}}}
<<<
This would be interesting, since it would be the native format for the [[Leo Outline Editor|http://webpages.charter.net/edreamleo/front.html]].
<<<
Everything else should be done by virtue of the HTML being really easy to change and modify, and the libraries making extra code really easy to write/copy and paste from other people. This would also have the benefit that the wikitext parser would be a lot simpler to grasp and write in other languages (i.e. it would be possible. Currently with the presence of macros it is only half possible).
<<<
The "enduser" shouldn't need to mess around with the HTML, but it should be possible if he wants. IMO the above paragraph only makes live easier for developers, and removes user value.
<<<
It goes without saying that the new wikitext parser would create correct HTML.
<<<
+1
<<<
I also realise that this (the removal of macros, etc) is perhaps a contentious issue. Suffice it to say that my motivations for doing so are in [[TiddlyLib Motivations]]@bengillies, and that I'd still like to keep things extensible and tweakable, just in a slightly different way.
<<<
Keeping things extensible and tweakable, just in a slightly different way, would be interesting. I'd like to get more info, how to manage that for the enduser.
!!!!2011.06.25
At [[A Journey Contacting New Members]]@espace ~@espace asks:
<<<
What the heck does "Reply to this tiddler mean?" I clicked on this link and
a new tiddler was created. I'm now editing the new tiiddler.
<<<
This is exactly, what it is supposed to do. "Reply to" is known from "conversation" oriented programms, so it may be a little bit confusing.
<<<
//Why can't I send mail to a tiddler?//
<<<
If you would send a message to my tiddler, it would effect my space. eg: my space would need to store it. With TiddlySpace, you write your thoughts into your space. If you mark/tag them with eg: ~@pmario, and I follow you, I can see them. This behaviour prevents spam per definition. Because you can't spam my space. Only yours.
<<<
Or why can't I have an inbox associated with my namespace?
<<<
I think @jon's linksocial plugin, can solve this issue, the ~TiddlySpace way. Also see: [[Linksocial vs Following Bubble vs Mailboxes]]@pmario
----
2011.06.24
!TiddlySpace and contacting a new member
* Some days ago cdent started to follow @espace
* I thought "Let's have a look"
** A new space and "surprise" there is some real content.
** [[Welcome]]@espace
** [[How Do I]]@espace ... (I thought .. OK I can help)
* Some interesting stuff
** ContentProviderVolunteers@espace
** [[TiddlySuck.erl]]@espace
!!!As an existing member, what do I have to do, to get in contact?
* TiddlySpace doesn't offer any default possibilities.
** TS doesn't collect an email address, ...
Welcome@espace {{{@espace}}} names the owner, and Google may know him.
>This is Joe Armstring's tiddlyspace.
Google search "Joe Armstring erlang" ... OK google seems to know him but there seems to by a typo. After some more searching I got an email address (from google groups) and fired a "shot in the dark". See: Following@espace. It worked.
''If it is that hard to get in contact for an existing member, it seems to be close to impossible for a new member!''
''What do you think?''
<html>
<head>
<title>Privateer</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"
type="text/javascript"></script>
<script src="/chrjs" type="text/javascript"></script>
<link rel="stylesheet" href="/bags/common/tiddlers/tiddlyweb.css" type="text/css" />
<style>
h1, ul {
padding-bottom: .5em;
}
</style>
</head>
<body>
<div id='header'>
<h1>Privateer</h1>
</div>
<div id='content'>
<div class="tiddler">
<h1>Make a Public URI for a Private one</h1>
<form name='privatize' id='privatize'
action='/_' method='POST'>
<select name='uri'>
<option value='view_space'>
Private View of this Space</option>
<option value='atom_space'>
Private Atom Feed of this Space</option>
<option value='view_tiddler'>
Private View of a single Tiddler</option>
<option value='atom_tiddler'>
Private Atom Feed of a single Tiddler</option>
</select>
<select name='tiddler' disabled>
</select>
<input type='submit' name='submit' />
<input type='hidden' name='csrf_token' />
</form>
</div>
<div id='message'></div>
<div class='tiddler'>
<h1>List Existing Mappings</h1>
<div>Show Mappings:
<input type='checkbox' name='shower' />
<div>
<form name='deletemachine'>
<ul id='mappings'>
</ul>
Select All: <input type='checkbox' name='selectall' />
<input type='Submit' name='Submit' value='Delete Selected' />
</form>
</div>
</div>
</body>
<script>
// form handling
(function() {
// doesn't work for BYOD
var location = window.location;
var spaceName = location.hostname.split('.', 1)[0];
var spaceURI = location.protocol + '//' + location.host + '/';
var privatizeForm = $('form[name=privatize]');
var deleteForm = $('form[name=deletemachine]');
var formAction = privatizeForm.attr('action');
var lister = $('#mappings');
var uriSelect = privatizeForm.children('select[name=uri]');
var tiddlerSelect = privatizeForm.children('select[name=tiddler]');
var readCookie = function(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length,c.length);
}
}
return null;
};
var updateCSRF = function(form) {
var token = readCookie('csrf_token');
var csrf_token = form.find("[name=csrf_token]");
csrf_token.val(token);
}
var updatePrivateSuccess = function(data, status, xhr) {
$.each(data, function(index, tiddler) {
$('<option>').val(tiddler.title).text(tiddler.title)
.appendTo(tiddlerSelect);
});
};
var updatePrivateError = function(xhr, status, exc) {
$('#message').text('Unable to get private tiddlers:' + xhr.statusText);
};
var updatePrivateTiddlers = function() {
var bag = new tiddlyweb.Bag(spaceName + '_private', spaceURI);
bag.tiddlers().get(updatePrivateSuccess, updatePrivateError);
};
var establishEvents = function() {
// listen for change on uri select
uriSelect.change(function() {
var current = $(this).val()
if (current.indexOf('_tiddler') != -1) {
tiddlerSelect.removeAttr('disabled');
} else {
tiddlerSelect.attr('disabled', 'true');
}
});
// XXX probably need to clear text other times too
tiddlerSelect.change(function() {
$('#message').text('');
});
// listen for submit on the form, process data, then submit
privatizeForm.submit(function() {
var csrf_token = privatizeForm.find("[name=csrf_token]").val();
var uri = uriSelect.val();
var tiddler = tiddlerSelect.val();
var atom = uri.indexOf('atom_') == -1 ? '' : '.atom';
var postingURI;
if (uri.indexOf('_tiddler') != -1) {
// we have a tiddler
if (tiddler && tiddler != '-') {
postingUri = spaceURI + encodeURIComponent(tiddler) + atom;
} else {
$('#message').text('You need to provide a tiddler title');
return false;
}
} else {
// we have a collection
if (atom) {
postingUri = spaceURI + 'recipes/' + spaceName + '_private/tiddlers' + atom;
} else {
postingUri = spaceURI;
}
}
$.ajax({url: formAction,
type: 'POST',
data: {uri: postingUri, csrf_token: csrf_token},
success: function(data, status, xhr) {
var location = xhr.getResponseHeader('location');
$('#message').text(location);
updateLister();
},
error: function(xhr, error, exc) {
$('#message').text('Error when posting: ' + xhr.statuText);
}
});
return false;
});
$('input[name=shower]').click(function() {
if ($('.mapping').is(':visible')) {
$('.mapping').hide();
} else {
$('.mapping').show();
}
});
$('input[name=selectall]').click(function() {
$('input[name=deletor]').each(function(index) {
$(this).attr('checked',
$('input[name=selectall]').attr('checked') ? true : false);
});
});
deleteForm.submit(function() {
var deletes = [];
$('input[name=deletor]').each(function(index) {
if ($(this).attr('checked')) {
deleteMap($(this).val());
}
})
return false;
});
};
var updateListerSuccess = function(data, status, xhr) {
lister.empty();
$.each(data, function(map, target) {
var el = $('<li />');
$('<input type="checkbox" name="deletor" />').val(map)
.appendTo(el);
$('<a />').attr('href', target).attr('title', map).text(target)
.appendTo(el);
$('<span />').text(map).addClass('mapping').hide().appendTo(el);
lister.append(el);
});
};
var updateListerError = function(xhr, error, exc) {
$('#message').text('Error when getting listings: ' + xhr.statusText);
}
var updateLister = function() {
$.ajax({ url: '/_',
type: 'GET',
dataType: 'json',
success: updateListerSuccess,
error: updateListerError
});
};
var deleteMap = function(target) {
$.ajax({
url: target,
type: 'DELETE',
success: function(data, status, xhr) {
updateLister();
},
error: function(xhr, error, exc) {
$('#message').text('Error when deleting listing: ' + xhr.statusText);
}
});
};
updateCSRF(privatizeForm);
establishEvents();
updatePrivateTiddlers();
updateLister();
})();
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Reply</title>
<link rel="stylesheet" href="http://tiddlyspace.com/bags/benspa_public/tiddlers/bootvelcro.css">
<style>
html,
body {
overflow: hidden;
background-color: transparent;
}
#container {
/* prevent a fouc if no images present */
display: none;
}
.modal-header {
border-bottom: none;
padding: 5px 0 0;
position: absolute;
width: 100%;
background-color: #e0e0e0;
-webkit-border-radius: 6px 6px 0 0;
-moz-border-radius: 6px 6px 0 0;
border-radius: 6px 6px 0 0;
cursor: move;
}
.form-actions {
position: absolute;
bottom: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
width: 100%;
margin: 0;
border-radius: 0 0 6px 6px;
background-color: #e0e0e0;
border-top: 1px solid gray;
}
.form-actions input.btn {
width: auto;
float: right;
margin: 0 0.2em;
}
.closeBtn {
background-color: #DCE7F1 !important;
}
.primary {
background-color: #09F !important;
}
h1 {
margin-bottom: 9px;
margin-top: 9px;
}
body {
width: 100%;
height: 100%;
position: absolute;
}
.modal {
margin: 10px;
top: 0;
left: 0;
bottom: 0;
width: 510px;
position: absolute;
box-shadow: #444 0px 0px 10px 2px;
border-radius: 6px;
background-color: white;
border: 1px solid gray;
background-color: #F0F4F8;
}
label em {
cursor: pointer;
}
.modal-body {
overflow: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 65px 20px 67px;
background-color: transparent;
}
.nav-tabs {
padding-left: 1%;;
margin: 0;
width: 99%;
border-color: gray;
}
.nav-tabs > li {
cursor: pointer;
}
.nav-tabs > li > a {
line-height: 2.4em;
font-weight: bold;
font-size: 100%;
}
.nav-tabs > li.active > a{
background-color: #F0F4F8;
border-color: gray;
border-bottom-color: #F0F4F8;
}
.active {
display: block;
}
input,
textarea,
select,
.uneditable-input {
color: #606060;
}
.imagePicker {
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
border: 1px solid #CCC;
height: 110px;
overflow: auto;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
margin-left: 0;
}
.imagePicker img {
margin: 5px;
border: 2px solid transparent;
}
.imagePicker .current {
border: 2px dotted #555;
}
label {
font-weight: bold;
}
.form-actions label {
float: left;
margin-top: 0.75em;
}
fieldset input,
fieldset textarea {
width: 90%;
border-color: gray;
}
@media all and (max-width: 550px) {
.modal {
width: 95%;
}
}
#help {
position: absolute;
border: 0;
right: 4px;
top: 5px;
text-indent: -9999px;
color: transparent;
height: 16px;
width: 16px;
background: none;
background-image: url(http://tiddlyspace.com/bags/common/tiddlers/help.png);
background-repeat: no-repeat;
background-color: white;
z-index: 2;
border-radius: 10px;
}
#help-info {
padding: 0;
border: 1px solid gray;
width: 60%;
height: 50px;
color: #404040;
background-color: white;
position: absolute;
top: 5px;
right: 5px;
z-index: 1;
cursor: auto;
border-radius: 5px;
}
#help-info p {
padding: 10px 25px;
margin-bottom: 0;
}
</style>
</head>
<body>
<div id="container">
<form action="#" class="modal">
<div class="modal-header">
<button id="help">help</button>
<div id="help-info" style="display:none;"><p>
Found something interesting? Write about it in your own space. <a href="http://docs.tiddlyspace.com/Reply to this Tiddler" target="_blank">Find out more</a>
</p></div>
<ul class="nav nav-tabs" data-tabs="tabs">
<li class="active" data-tab-name="post"><a href="#postForm">Reply</a></li>
</ul>
</div>
<fieldset id="postForm" class="modal-body">
<label>Title
<input type="text" name="title">
</label>
<input type="hidden" name="url">
<label>Post
<textarea name="text" rows="8"></textarea>
</label>
<label>Tags
<input type="text" name="tags" value="">
</label>
</fieldset>
<div class="form-actions">
<label class="checkbox">
<input type="checkbox" name="private" val="private">
keep private
</label>
<input type="submit" class="btn primary btn-large" value="Done">
<input type="button" class="btn btn-large closeBtn" value="Cancel">
</div>
</form>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="http://tiddlyspace.com/bags/tiddlyspace/tiddlers/chrjs"></script>
<script type="text/javascript" src="/bags/common/tiddlers/_reply.js"></script>
</body>
</html>
@@Please do not modify this tiddler; it was created automatically upon space creation.@@
<<tiddler FollowTemplate>>
In reply to [[Hey from g]]@stevesuny at @stevesuny
Hi Steve,
I've seen some of your questions. I'm busy with codemirror at the moment, so just a short info.
Also saw [[Today's Frustrations]]@stevesuny.
* The newHere problem can be solved, if you include the @neui-toolbar space.
** newHere is a macro, not a toolbar command. the neui-toolbar space includes a "newTagged" command. See my ToolbarCommands@pmario tiddler
** A [[GoogleGroups topic|http://groups.google.com/group/tiddlywiki/browse_thread/thread/cab3a6775e99890e]] that may be of interest
* @neui-tagsearch space may be interesting for you too. Both are designed to work with neui-em theme.
have fun!
-m
/***
Copyright (C) 2011 by Marijn Haverbeke <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
***/
//{{{
// All functions that need access to the editor's state live inside
// the CodeMirror function. Below that, at the bottom of the file,
// some utilities are defined.
// CodeMirror is the only global var we claim
var CodeMirror=function(){function e(r,i){function $t(e){return e>=0&&e<yt.size}function Kt(e){return E(yt,e)}function Qt(e,t){Ht=!0;var n=t-e.height;for(var r=e;r;r=r.parent)r.height+=n}function Gt(e){var t={line:0,ch:0};dn(t,{line:yt.size-1,ch:Kt(yt.size-1).text.length},it(e),t,t),At=!0}function Yt(e){var t=[];return yt.iter(0,yt.size,function(e){t.push(e.text)}),t.join("\n")}function Zt(e){function f(e){var t=Dr(e,!0);if(t&&!Q(t,o)){wt||hn(),o=t,Rn(r,t),At=!1;var n=Pn();if(t.line>=n.to||t.line<n.from)u=setTimeout(Vr(function(){f(e)}),150)}}function l(e){clearTimeout(u);var t=Dr(e);t&&Rn(r,t),L(e),On(),At=!0,c(),a()}qn(D(e,"shiftKey"));for(var t=M(e);t!=y;t=t.parentNode)if(t.parentNode==X&&t!=V)return;for(var t=M(e);t!=y;t=t.parentNode)if(t.parentNode==ut)return s.onGutterClick&&s.onGutterClick(Jt,nt(ut.childNodes,t)+Ft,e),L(e);var r=Dr(e);switch(_(e)){case 3:j&&!n&&Pr(e);return;case 2:r&&Wn(r.line,r.ch,!0);return}if(!r){M(e)==W&&L(e);return}wt||hn();var i=+(new Date);if(Tt&&Tt.time>i-400&&Q(Tt.pos,r))return L(e),setTimeout(On,20),Zn(r.line);if(xt&&xt.time>i-400&&Q(xt.pos,r))return Tt={time:i,pos:r},L(e),Yn(r);xt={time:i,pos:r};var o=r,u;if(z&&!s.readOnly&&!Q(Et.from,Et.to)&&!G(r,Et.from)&&!G(Et.to,r)){q&&(at.draggable=!0);var a=P(document,"mouseup",Vr(function(t){q&&(at.draggable=!1),Ct=!1,a(),Math.abs(e.clientX-t.clientX)+Math.abs(e.clientY-t.clientY)<10&&(L(t),Wn(r.line,r.ch,!0),On())}),!0);Ct=!0,at.dragDrop&&at.dragDrop();return}L(e),Wn(r.line,r.ch,!0);var c=P(document,"mousemove",Vr(function(e){clearTimeout(u),L(e),!F&&!_(e)?l(e):f(e)}),!0),a=P(document,"mouseup",Vr(l),!0)}function en(e){for(var t=M(e);t!=y;t=t.parentNode)if(t.parentNode==ut)return L(e);var n=Dr(e);if(!n)return;Tt={time:+(new Date),pos:n},L(e),Yn(n)}function tn(e){e.preventDefault();var t=Dr(e,!0),n=e.dataTransfer.files;if(!t||s.readOnly)return;if(n&&n.length&&window.FileReader&&window.File){function r(e,n){var r=new FileReader;r.onload=function(){o[n]=r.result,++u==i&&(t=Vn(t),Vr(function(){var e=bn(o.join(""),t,t);Rn(t,e)})())},r.readAsText(e)}var i=n.length,o=Array(i),u=0;for(var a=0;a<i;++a)r(n[a],a)}else try{var o=e.dataTransfer.getData("Text");if(o){var f=Et.from,l=Et.to;Rn(t,t),Ct&&bn("",f,l),wn(o),On()}}catch(e){}}function nn(e){var t=xn();e.dataTransfer.setData("Text",t);if(j||R){var n=document.createElement("img");n.scr="data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs=",e.dataTransfer.setDragImage(n,0,0)}}function rn(e,t){if(typeof e=="string"){e=u[e];if(!e)return!1}var n=St;try{s.readOnly&&(Lt=!0),t&&(St=null),e(Jt)}catch(r){if(r!=B)throw r;return!1}finally{St=n,Lt=!1}return!0}function sn(e){var t=f(s.keyMap),n=t.auto;clearTimeout(an),n&&!c(e)&&(an=setTimeout(function(){f(s.keyMap)==t&&(s.keyMap=n.call?n.call(null,Jt):n)},50));var r=ot[D(e,"keyCode")],i=!1;return r==null||e.altGraphKey?!1:(D(e,"altKey")&&(r="Alt-"+r),D(e,"ctrlKey")&&(r="Ctrl-"+r),D(e,"metaKey")&&(r="Cmd-"+r),D(e,"shiftKey")?i=l("Shift-"+r,s.extraKeys,s.keyMap,function(e){return rn(e,!0)})||l(r,s.extraKeys,s.keyMap,function(e){if(typeof e=="string"&&/^go[A-Z]/.test(e))return rn(e)}):i=l(r,s.extraKeys,s.keyMap,rn),i&&(L(e),F&&(e.oldKeyCode=e.keyCode,e.keyCode=0)),i)}function on(e,t){var n=l("'"+t+"'",s.extraKeys,s.keyMap,rn);return n&&L(e),n}function fn(e){wt||hn(),F&&e.keyCode==27&&(e.returnValue=!1),Tn&&Ln()&&(Tn=!1);if(s.onKeyEvent&&s.onKeyEvent(Jt,k(e)))return;var t=D(e,"keyCode");qn(t==16||D(e,"shiftKey"));var r=sn(e);window.opera&&(un=r?t:null,!r&&t==88&&D(e,n?"metaKey":"ctrlKey")&&wn(""))}function ln(e){Tn&&Ln();if(s.onKeyEvent&&s.onKeyEvent(Jt,k(e)))return;var t=D(e,"keyCode"),n=D(e,"charCode");if(window.opera&&t==un){un=null,L(e);return}if((window.opera&&!e.which||U)&&sn(e))return;var r=String.fromCharCode(n==null?t:n);s.electricChars&>.electricChars&&s.smartIndent&&!s.readOnly&>.electricChars.indexOf(r)>-1&&setTimeout(Vr(function(){tr(Et.to.line,"smart")}),75);if(on(e,r))return;Cn()}function cn(e){if(s.onKeyEvent&&s.onKeyEvent(Jt,k(e)))return;D(e,"keyCode")==16&&(St=null)}function hn(){if(s.readOnly=="nocursor")return;wt||(s.onFocus&&s.onFocus(Jt),wt=!0,y.className.search(/\bCodeMirror-focused\b/)==-1&&(y.className+=" CodeMirror-focused"),Pt||An(!0)),Nn(),Hr()}function pn(){wt&&(s.onBlur&&s.onBlur(Jt),wt=!1,Rt&&Vr(function(){Rt&&(Rt(),Rt=null)})(),y.className=y.className.replace(" CodeMirror-focused","")),clearInterval(mt),setTimeout(function(){wt||(St=null)},150)}function dn(e,t,n,r,i){if(Lt)return;if(Xt){var o=[];yt.iter(e.line,t.line+1,function(e){o.push(e.text)}),Xt.addChange(e.line,n.length,o);while(Xt.done.length>s.undoDepth)Xt.done.shift()}yn(e,t,n,r,i)}function vn(e,t){if(!e.length)return;var n=e.pop(),r=[];for(var i=n.length-1;i>=0;i-=1){var s=n[i],o=[],u=s.start+s.added;yt.iter(s.start,u,function(e){o.push(e.text)}),r.push({start:s.start,added:s.old.length,old:o});var a=Vn({line:s.start+s.old.length-1,ch:tt(o[o.length-1],s.old[s.old.length-1])});yn({line:s.start,ch:0},{line:u-1,ch:Kt(u-1).text.length},s.old,a,a)}At=!0,t.push(r)}function mn(){vn(Xt.done,Xt.undone)}function gn(){vn(Xt.undone,Xt.done)}function yn(e,t,n,r,i){function T(e){return e<=Math.min(t.line,t.line+y)?e:e+y}if(Lt)return;var o=!1,u=Ut.length;s.lineWrapping||yt.iter(e.line,t.line,function(e){if(e.text.length==u)return o=!0,!0});if(e.line!=t.line||n.length>1)Ht=!0;var a=t.line-e.line,f=Kt(e.line),l=Kt(t.line);if(e.ch==0&&t.ch==0&&n[n.length-1]==""){var c=[],h=null;e.line?(h=Kt(e.line-1),h.fixMarkEnds(l)):l.fixMarkStarts();for(var p=0,d=n.length-1;p<d;++p)c.push(g.inheritMarks(n[p],h));a&&yt.remove(e.line,a,Bt),c.length&&yt.insert(e.line,c)}else if(f==l)if(n.length==1)f.replace(e.ch,t.ch,n[0]);else{l=f.split(t.ch,n[n.length-1]),f.replace(e.ch,null,n[0]),f.fixMarkEnds(l);var c=[];for(var p=1,d=n.length-1;p<d;++p)c.push(g.inheritMarks(n[p],f));c.push(l),yt.insert(e.line+1,c)}else if(n.length==1)f.replace(e.ch,null,n[0]),l.replace(null,t.ch,""),f.append(l),yt.remove(e.line+1,a,Bt);else{var c=[];f.replace(e.ch,null,n[0]),l.replace(null,t.ch,n[n.length-1]),f.fixMarkEnds(l);for(var p=1,d=n.length-1;p<d;++p)c.push(g.inheritMarks(n[p],f));a>1&&yt.remove(e.line+1,a-1,Bt),yt.insert(e.line+1,c)}if(s.lineWrapping){var v=W.clientWidth/Or()-3;yt.iter(e.line,e.line+n.length,function(e){if(e.hidden)return;var t=Math.ceil(e.text.length/v)||1;t!=e.height&&Qt(e,t)})}else yt.iter(e.line,p+n.length,function(e){var t=e.text;t.length>u&&(Ut=t,u=t.length,zt=null,o=!1)}),o&&(u=0,Ut="",zt=null,yt.iter(0,yt.size,function(e){var t=e.text;t.length>u&&(u=t.length,Ut=t)}));var m=[],y=n.length-a-1;for(var p=0,b=bt.length;p<b;++p){var w=bt[p];w<e.line?m.push(w):w>t.line&&m.push(w+y)}var E=e.line+Math.min(n.length,500);qr(e.line,E),m.push(E),bt=m,Ur(100),Mt.push({from:e.line,to:t.line+1,diff:y});var S={from:e,to:t,text:n};if(_t){for(var x=_t;x.next;x=x.next);x.next=S}else _t=S;Un(r,i,T(Et.from.line),T(Et.to.line)),W.clientHeight&&(X.style.height=yt.height*kr()+2*Mr()+"px")}function bn(e,t,n){function r(r){if(G(r,t))return r;if(!G(n,r))return i;var s=r.line+e.length-(n.line-t.line)-1,o=r.ch;return r.line==n.line&&(o+=e[e.length-1].length-(n.ch-(n.line==t.line?t.ch:0))),{line:s,ch:o}}t=Vn(t),n?n=Vn(n):n=t,e=it(e);var i;return En(e,t,n,function(e){return i=e,{from:r(Et.from),to:r(Et.to)}}),i}function wn(e,t){En(it(e),Et.from,Et.to,function(e){return t=="end"?{from:e,to:e}:t=="start"?{from:Et.from,to:Et.from}:{from:Et.from,to:e}})}function En(e,t,n,r){var i=e.length==1?e[0].length+t.ch:e[e.length-1].length,s=r({line:t.line+e.length-1,ch:i});dn(t,n,e,s.from,s.to)}function Sn(e,t){var n=e.line,r=t.line;if(n==r)return Kt(n).text.slice(e.ch,t.ch);var i=[Kt(n).text.slice(e.ch)];return yt.iter(n+1,r,function(e){i.push(e.text)}),i.push(Kt(r).text.slice(0,t.ch)),i.join("\n")}function xn(){return Sn(Et.from,Et.to)}function Nn(){if(Tn)return;dt.set(s.pollInterval,function(){zr(),Ln(),wt&&Nn(),Wr()})}function Cn(){function t(){zr();var n=Ln();!n&&!e?(e=!0,dt.set(60,t)):(Tn=!1,Nn()),Wr()}var e=!1;Tn=!0,dt.set(20,t)}function Ln(){if(Pt||!wt||st(A)||s.readOnly)return!1;var e=A.value;if(e==kn)return!1;St=null;var t=0,n=Math.min(kn.length,e.length);while(t<n&&kn[t]==e[t])++t;return t<kn.length?Et.from={line:Et.from.line,ch:Et.from.ch-(kn.length-t)}:kt&&Q(Et.from,Et.to)&&(Et.to={line:Et.to.line,ch:Math.min(Kt(Et.to.line).text.length,Et.to.ch+(e.length-t))}),wn(e.slice(t),"end"),kn=e,!0}function An(e){Q(Et.from,Et.to)?e&&(kn=A.value=""):(kn="",A.value=xn(),K(A))}function On(){s.readOnly!="nocursor"&&A.focus()}function Mn(){if(!lt.getBoundingClientRect)return;var e=lt.getBoundingClientRect();if(F&&e.top==e.bottom)return;var t=window.innerHeight||Math.max(document.body.offsetHeight,document.documentElement.offsetHeight);(e.top<0||e.bottom>t)&<.scrollIntoView()}function _n(){var e=Er(Et.inverted?Et.from:Et.to),t=s.lineWrapping?Math.min(e.x,at.offsetWidth):e.x;return Dn(t,e.y,t,e.yBot)}function Dn(e,t,n,r){var i=_r(),o=Mr();t+=o,r+=o,e+=i,n+=i;var u=W.clientHeight,a=W.scrollTop,f=!1,l=!0;t<a?(W.scrollTop=Math.max(0,t),f=!0):r>a+u&&(W.scrollTop=r-u,f=!0);var c=W.clientWidth,h=W.scrollLeft,p=s.fixedGutter?Z.clientWidth:0;return e<h+p?(e<50&&(e=0),W.scrollLeft=Math.max(0,e-10-p),f=!0):n>c+h-3&&(W.scrollLeft=n+10-c,f=!0,n>X.clientWidth&&(l=!1)),f&&s.onScroll&&s.onScroll(Jt),l}function Pn(){var e=kr(),t=W.scrollTop-Mr(),n=Math.max(0,Math.floor(t/e)),r=Math.ceil((t+W.clientHeight)/e);return{from:x(yt,n),to:x(yt,r)}}function Hn(e,t){function p(){zt=W.clientWidth;var e=ht.firstChild,t=!1;return yt.iter(Ft,It,function(n){if(!n.hidden){var r=Math.round(e.offsetHeight/l)||1;n.height!=r&&(Qt(n,r),Ht=t=!0)}e=e.nextSibling}),t&&(X.style.height=yt.height*l+2*Mr()+"px"),t}if(!W.clientWidth){Ft=It=jt=0;return}var n=Pn();if(e!==!0&&e.length==0&&n.from>Ft&&n.to<It)return;var r=Math.max(n.from-100,0),i=Math.min(yt.size,n.to+100);Ft<r&&r-Ft<20&&(r=Ft),It>i&&It-i<20&&(i=Math.min(yt.size,It));var o=e===!0?[]:Bn([{from:Ft,to:It,domStart:0}],e),u=0;for(var a=0;a<o.length;++a){var f=o[a];f.from<r&&(f.domStart+=r-f.from,f.from=r),f.to>i&&(f.to=i),f.from>=f.to?o.splice(a--,1):u+=f.to-f.from}if(u==i-r)return;o.sort(function(e,t){return e.domStart-t.domStart});var l=kr(),c=Z.style.display;ht.style.display="none",jn(r,i,o),ht.style.display=Z.style.display="";var h=r!=Ft||i!=It||qt!=W.clientHeight+l;h&&(qt=W.clientHeight+l),Ft=r,It=i,jt=T(yt,r),V.style.top=jt*l+"px",W.clientHeight&&(X.style.height=yt.height*l+2*Mr()+"px");if(ht.childNodes.length!=It-Ft)throw new Error("BAD PATCH! "+JSON.stringify(o)+" size="+(It-Ft)+" nodes="+ht.childNodes.length);return s.lineWrapping?p():(zt==null&&(zt=gr(Ut)),zt>W.clientWidth?(at.style.width=zt+"px",X.style.width="",X.style.width=W.scrollWidth+"px"):at.style.width=X.style.width=""),Z.style.display=c,(h||Ht)&&Fn()&&s.lineWrapping&&p()&&Fn(),In(),!t&&s.onUpdate&&s.onUpdate(Jt),!0}function Bn(e,t){for(var n=0,r=t.length||0;n<r;++n){var i=t[n],s=[],o=i.diff||0;for(var u=0,a=e.length;u<a;++u){var f=e[u];i.to<=f.from&&i.diff?s.push({from:f.from+o,to:f.to+o,domStart:f.domStart}):i.to<=f.from||i.from>=f.to?s.push(f):(i.from>f.from&&s.push({from:f.from,to:i.from,domStart:f.domStart}),i.to<f.to&&s.push({from:i.to+o,to:f.to+o,domStart:f.domStart+(i.to-f.from)}))}e=s}return e}function jn(e,t,n){if(!n.length)ht.innerHTML="";else{function r(e){var t=e.nextSibling;return e.parentNode.removeChild(e),t}var i=0,s=ht.firstChild,o;for(var u=0;u<n.length;++u){var a=n[u];while(a.domStart>i)s=r(s),i++;for(var f=0,l=a.to-a.from;f<l;++f)s=s.nextSibling,i++}while(s)s=r(s)}var c=n.shift(),s=ht.firstChild,f=e,h=document.createElement("div");yt.iter(e,t,function(e){c&&c.to==f&&(c=n.shift());if(!c||c.from>f){if(e.hidden)var t=h.innerHTML="<pre></pre>";else{var t="<pre"+(e.className?' class="'+e.className+'"':"")+">"+e.getHTML(sr)+"</pre>";e.bgClassName&&(t='<div style="position: relative"><pre class="'+e.bgClassName+'" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2"> </pre>'+t+"</div>")}h.innerHTML=t,ht.insertBefore(h.firstChild,s)}else s=s.nextSibling;++f})}function Fn(){if(!s.gutter&&!s.lineNumbers)return;var e=V.offsetHeight,t=W.clientHeight;Z.style.height=(e-t<2?t:e)+"px";var n=[],r=Ft,i;yt.iter(Ft,Math.max(It,Ft+1),function(e){if(e.hidden)n.push("<pre></pre>");else{var t=e.gutterMarker,o=s.lineNumbers?r+s.firstLineNumber:null;t&&t.text?o=t.text.replace("%N%",o!=null?o:""):o==null&&(o="\u00a0"),n.push(t&&t.style?'<pre class="'+t.style+'">':"<pre>",o);for(var u=1;u<e.height;++u)n.push("<br/> ");n.push("</pre>"),t||(i=r)}++r}),Z.style.display="none",ut.innerHTML=n.join("");if(i!=null){var o=ut.childNodes[i-Ft],u=String(yt.size).length,a=J(o),f="";while(a.length+f.length<u)f+="\u00a0";f&&o.insertBefore(document.createTextNode(f),o.firstChild)}Z.style.display="";var l=Math.abs((parseInt(at.style.marginLeft)||0)-Z.offsetWidth)>2;return at.style.marginLeft=Z.offsetWidth+"px",Ht=!1,l}function In(){var e=Q(Et.from,Et.to),t=Er(Et.from,!0),n=e?t:Er(Et.to,!0),r=Et.inverted?t:n,i=kr(),o=$(y),u=$(ht);C.style.top=Math.max(0,Math.min(W.offsetHeight,r.y+u.top-o.top))+"px",C.style.left=Math.max(0,Math.min(W.offsetWidth,r.x+u.left-o.left))+"px";if(e)lt.style.top=r.y+"px",lt.style.left=(s.lineWrapping?Math.min(r.x,at.offsetWidth):r.x)+"px",lt.style.display="",ct.style.display="none";else{var a=t.y==n.y,f="";function l(e,t,n,r){f+='<div class="CodeMirror-selected" style="position: absolute; left: '+e+"px; top: "+t+"px; right: "+n+"px; height: "+r+'px"></div>'}var c=at.clientWidth||at.offsetWidth,h=at.clientHeight||at.offsetHeight;if(Et.from.ch&&t.y>=0){var p=a?c-n.x:0;l(t.x,t.y,p,i)}var d=Math.max(0,t.y+(Et.from.ch?i:0)),v=Math.min(n.y,h)-d;v>.2*i&&l(0,d,0,v),(!a||!Et.from.ch)&&n.y<h-.5*i&&l(0,n.y,c-n.x,i),ct.innerHTML=f,lt.style.display="none",ct.style.display=""}}function qn(e){e?St=St||(Et.inverted?Et.to:Et.from):St=null}function Rn(e,t){var n=St&&Vn(St);n&&(G(n,e)?e=n:G(t,n)&&(t=n)),Un(e,t),Ot=!0}function Un(e,t,n,r){Qn=null,n==null&&(n=Et.from.line,r=Et.to.line);if(Q(Et.from,e)&&Q(Et.to,t))return;if(G(t,e)){var i=t;t=e,e=i}if(e.line!=n){var o=zn(e,n,Et.from.ch);o?e=o:vr(e.line,!1)}t.line!=r&&(t=zn(t,r,Et.to.ch)),Q(e,t)?Et.inverted=!1:Q(e,Et.to)?Et.inverted=!1:Q(t,Et.from)&&(Et.inverted=!0);if(s.autoClearEmptyLines&&Q(Et.from,Et.to)){var u=Et.inverted?e:t;if(u.line!=Et.from.line&&Et.from.line<yt.size){var a=Kt(Et.from.line);/^\s+$/.test(a.text)&&setTimeout(Vr(function(){if(a.parent&&/^\s+$/.test(a.text)){var e=S(a);bn("",{line:e,ch:0},{line:e,ch:a.text.length})}},10))}}Et.from=e,Et.to=t,Dt=!0}function zn(e,t,n){function r(t){var r=e.line+t,i=t==1?yt.size:-1;while(r!=i){var s=Kt(r);if(!s.hidden){var o=e.ch;if(o>n||o>s.text.length)o=s.text.length;return{line:r,ch:o}}r+=t}}var i=Kt(e.line);return i.hidden?e.line>=t?r(1)||r(-1):r(-1)||r(1):e}function Wn(e,t,n){var r=Vn({line:e,ch:t||0});(n?Rn:Un)(r,r)}function Xn(e){return Math.max(0,Math.min(e,yt.size-1))}function Vn(e){if(e.line<0)return{line:0,ch:0};if(e.line>=yt.size)return{line:yt.size-1,ch:Kt(yt.size-1).text.length};var t=e.ch,n=Kt(e.line).text.length;return t==null||t>n?{line:e.line,ch:n}:t<0?{line:e.line,ch:0}:e}function $n(e,t){function o(){for(var t=r+e,n=e<0?-1:yt.size;t!=n;t+=e){var i=Kt(t);if(!i.hidden)return r=t,s=i,!0}}function u(t){if(i==(e<0?0:s.text.length)){if(!!t||!o())return!1;i=e<0?s.text.length:0}else i+=e;return!0}var n=Et.inverted?Et.from:Et.to,r=n.line,i=n.ch,s=Kt(r);if(t=="char")u();else if(t=="column")u(!0);else if(t=="word"){var a=!1;for(;;){if(e<0&&!u())break;if(rt(s.text.charAt(i)))a=!0;else if(a){e<0&&(e=1,u());break}if(e>0&&!u())break}}return{line:r,ch:i}}function Jn(e,t){var n=e<0?Et.from:Et.to;if(St||Q(Et.from,Et.to))n=$n(e,t);Wn(n.line,n.ch,!0)}function Kn(e,t){Q(Et.from,Et.to)?e<0?bn("",$n(e,t),Et.to):bn("",Et.from,$n(e,t)):bn("",Et.from,Et.to),Ot=!0}function Gn(e,t){var n=0,r=Er(Et.inverted?Et.from:Et.to,!0);Qn!=null&&(r.x=Qn),t=="page"?n=Math.min(W.clientHeight,window.innerHeight||document.documentElement.clientHeight):t=="line"&&(n=kr());var i=Sr(r.x,r.y+n*e+2);t=="page"&&(W.scrollTop+=Er(i,!0).y-r.y),Wn(i.line,i.ch,!0),Qn=r.x}function Yn(e){var t=Kt(e.line).text,n=e.ch,r=e.ch;while(n>0&&rt(t.charAt(n-1)))--n;while(r<t.length&&rt(t.charAt(r)))++r;Rn({line:e.line,ch:n},{line:e.line,ch:r})}function Zn(e){Rn({line:e,ch:0},Vn({line:e+1,ch:0}))}function er(e){if(Q(Et.from,Et.to))return tr(Et.from.line,e);var t=Et.to.line-(Et.to.ch?0:1);for(var n=Et.from.line;n<=t;++n)tr(n,e)}function tr(e,t){t||(t="add");if(t=="smart")if(!gt.indent)t="prev";else var n=Ir(e);var r=Kt(e),i=r.indentation(s.tabSize),o=r.text.match(/^\s*/)[0],u;t=="prev"?e?u=Kt(e-1).indentation(s.tabSize):u=0:t=="smart"?u=gt.indent(n,r.text.slice(o.length),r.text):t=="add"?u=i+s.indentUnit:t=="subtract"&&(u=i-s.indentUnit),u=Math.max(0,u);var a=u-i;if(!a){if(Et.from.line!=e&&Et.to.line!=e)return;var f=o}else{var f="",l=0;if(s.indentWithTabs)for(var c=Math.floor(u/s.tabSize);c;--c)l+=s.tabSize,f+=" ";while(l<u)++l,f+=" "}bn(f,{line:e,ch:0},{line:e,ch:o.length})}function nr(){gt=e.getMode(s,s.mode),yt.iter(0,yt.size,function(e){e.stateAfter=null}),bt=[0],Ur()}function rr(){var e=s.gutter||s.lineNumbers;Z.style.display=e?"":"none",e?Ht=!0:ht.parentNode.style.marginLeft=0}function ir(e,t){if(s.lineWrapping){y.className+=" CodeMirror-wrap";var n=W.clientWidth/Or()-3;yt.iter(0,yt.size,function(e){if(e.hidden)return;var t=Math.ceil(e.text.length/n)||1;t!=1&&Qt(e,t)}),at.style.width=X.style.width=""}else y.className=y.className.replace(" CodeMirror-wrap",""),zt=null,Ut="",yt.iter(0,yt.size,function(e){e.height!=1&&!e.hidden&&Qt(e,1),e.text.length>Ut.length&&(Ut=e.text)});Mt.push({from:0,to:yt.size})}function sr(e){var t=s.tabSize-e%s.tabSize,n=Wt[t];if(n)return n;for(var r='<span class="cm-tab">',i=0;i<t;++i)r+=" ";return Wt[t]={html:r+"</span>",width:t}}function or(){W.className=W.className.replace(/\s*cm-s-\w+/g,"")+s.theme.replace(/(^|\s)\s*/g," cm-s-")}function ur(){this.set=[]}function ar(e,t,n){function i(e,t,n,i){Kt(e).addMark(new v(t,n,i,r))}e=Vn(e),t=Vn(t);var r=new ur;if(!G(e,t))return r;if(e.line==t.line)i(e.line,e.ch,t.ch,n);else{i(e.line,e.ch,null,n);for(var s=e.line+1,o=t.line;s<o;++s)i(s,null,null,n);i(t.line,null,t.ch,n)}return Mt.push({from:e.line,to:t.line+1}),r}function fr(e){e=Vn(e);var t=new m(e.ch);return Kt(e.line).addMark(t),t}function lr(e){e=Vn(e);var t=[],n=Kt(e.line).marked;if(!n)return t;for(var r=0,i=n.length;r<i;++r){var s=n[r];(s.from==null||s.from<=e.ch)&&(s.to==null||s.to>=e.ch)&&t.push(s.marker||s)}return t}function cr(e,t,n){return typeof e=="number"&&(e=Kt(Xn(e))),e.gutterMarker={text:t,style:n},Ht=!0,e}function hr(e){typeof e=="number"&&(e=Kt(Xn(e))),e.gutterMarker=null,Ht=!0}function pr(e,t){var n=e,r=e;return typeof e=="number"?r=Kt(Xn(e)):n=S(e),n==null?null:t(r,n)?(Mt.push({from:n,to:n+1}),r):null}function dr(e,t,n){return pr(e,function(e){if(e.className!=t||e.bgClassName!=n)return e.className=t,e.bgClassName=n,!0})}function vr(e,t){return pr(e,function(e,n){if(e.hidden!=t){e.hidden=t,Qt(e,t?0:1);var r=Et.from.line,i=Et.to.line;if(t&&(r==n||i==n)){var s=r==n?zn({line:r,ch:0},r,0):Et.from,o=i==n?zn({line:i,ch:0},i,0):Et.to;if(!o)return;Un(s,o)}return Ht=!0}})}function mr(e){if(typeof e=="number"){if(!$t(e))return null;var t=e;e=Kt(e);if(!e)return null}else{var t=S(e);if(t==null)return null}var n=e.gutterMarker;return{line:t,handle:e,text:e.text,markerText:n&&n.text,markerClass:n&&n.style,lineClass:e.className,bgClass:e.bgClassName}}function gr(e){return ft.innerHTML="<pre><span>x</span></pre>",ft.firstChild.firstChild.firstChild.nodeValue=e,ft.firstChild.firstChild.offsetWidth||10}function yr(e,t){function i(e){return ft.innerHTML="<pre><span>"+n.getHTML(sr,e)+"</span></pre>",ft.firstChild.firstChild.offsetWidth}if(t<=0)return 0;var n=Kt(e),r=n.text,s=0,o=0,u=r.length,a,f=Math.min(u,Math.ceil(t/Or()));for(;;){var l=i(f);if(!(l<=t&&f<u)){a=l,u=f;break}f=Math.min(u,Math.ceil(f*1.2))}if(t>a)return u;f=Math.floor(u*.8),l=i(f),l<t&&(s=f,o=l);for(;;){if(u-s<=1)return a-t>t-o?s:u;var c=Math.ceil((s+u)/2),h=i(c);h>t?(u=c,a=h):(s=c,o=h)}}function wr(e,t){if(t==0)return{top:0,left:0};var n="";if(s.lineWrapping){var r=e.text.indexOf(" ",t+6);n=et(e.text.slice(t+1,r<0?e.text.length:r+(F?5:0)))}ft.innerHTML="<pre>"+e.getHTML(sr,t)+'<span id="CodeMirror-temp-'+br+'">'+et(e.text.charAt(t)||" ")+"</span>"+n+"</pre>";var i=document.getElementById("CodeMirror-temp-"+br),o=i.offsetTop,u=i.offsetLeft;if(F&&o==0&&u==0){var a=document.createElement("span");a.innerHTML="x",i.parentNode.insertBefore(a,i.nextSibling),o=a.offsetTop}return{top:o,left:u}}function Er(e,t){var n,r=kr(),i=r*(T(yt,e.line)-(t?jt:0));if(e.ch==0)n=0;else{var o=wr(Kt(e.line),e.ch);n=o.left,s.lineWrapping&&(i+=Math.max(0,o.top))}return{x:n,y:i,yBot:i+r}}function Sr(e,t){function c(e){var t=wr(u,e);if(f){var r=Math.round(t.top/n);return Math.max(0,t.left+(r-l)*W.clientWidth)}return t.left}t<0&&(t=0);var n=kr(),r=Or(),i=jt+Math.floor(t/n),o=x(yt,i);if(o>=yt.size)return{line:yt.size-1,ch:Kt(yt.size-1).text.length};var u=Kt(o),a=u.text,f=s.lineWrapping,l=f?i-T(yt,o):0;if(e<=0&&l==0)return{line:o,ch:0};var h=0,p=0,d=a.length,v,m=Math.min(d,Math.ceil((e+l*W.clientWidth*.9)/r));for(;;){var g=c(m);if(!(g<=e&&m<d)){v=g,d=m;break}m=Math.min(d,Math.ceil(m*1.2))}if(e>v)return{line:o,ch:d};m=Math.floor(d*.8),g=c(m),g<e&&(h=m,p=g);for(;;){if(d-h<=1)return{line:o,ch:v-e>e-p?h:d};var y=Math.ceil((h+d)/2),b=c(y);b>e?(d=y,v=b):(h=y,p=b)}}function xr(e){var t=Er(e,!0),n=$(at);return{x:n.left+t.x,y:n.top+t.y,yBot:n.top+t.yBot}}function kr(){if(Cr==null){Cr="<pre>";for(var e=0;e<49;++e)Cr+="x<br/>";Cr+="x</pre>"}var t=ht.clientHeight;return t==Nr?Tr:(Nr=t,ft.innerHTML=Cr,Tr=ft.firstChild.offsetHeight/50||1,ft.innerHTML="",Tr)}function Or(){return W.clientWidth==Ar?Lr:(Ar=W.clientWidth,Lr=gr("x"))}function Mr(){return at.offsetTop}function _r(){return at.offsetLeft}function Dr(e,t){var n=$(W,!0),r,i;try{r=e.clientX,i=e.clientY}catch(e){return null}if(!t&&(r-n.left>W.clientWidth||i-n.top>W.clientHeight))return null;var s=$(at,!0);return Sr(r-s.left,i-s.top)}function Pr(e){function s(){var e=it(A.value).join("\n");e!=i&&Vr(wn)(e,"end"),C.style.position="relative",A.style.cssText=r,I&&(W.scrollTop=n),Pt=!1,An(!0),Nn()}var t=Dr(e),n=W.scrollTop;if(!t||window.opera)return;(Q(Et.from,Et.to)||G(t,Et.from)||!G(t,Et.to))&&Vr(Wn)(t.line,t.ch);var r=A.style.cssText;C.style.position="absolute",A.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(e.clientY-5)+"px; left: "+(e.clientX-5)+"px; z-index: 1000; background: white; "+"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",Pt=!0;var i=A.value=xn();On(),K(A);if(j){O(e);var o=P(window,"mouseup",function(){o(),setTimeout(s,20)},!0)}else setTimeout(s,50)}function Hr(){clearInterval(mt);var e=!0;lt.style.visibility="",mt=setInterval(function(){lt.style.visibility=(e=!e)?"":"hidden"},650)}function jr(e){function v(e,t,n){if(!e.text)return;var r=e.styles,i=o?0:e.text.length-1,s;for(var a=o?0:r.length-2,f=o?r.length:-2;a!=f;a+=2*u){var l=r[a];if(r[a+1]!=null&&r[a+1]!=h){i+=u*l.length;continue}for(var c=o?0:l.length-1,v=o?l.length:-1;c!=v;c+=u,i+=u)if(i>=t&&i<n&&d.test(s=l.charAt(c))){var m=Br[s];if(m.charAt(1)==">"==o)p.push(s);else{if(p.pop()!=m.charAt(0))return{pos:i,match:!1};if(!p.length)return{pos:i,match:!0}}}}}var t=Et.inverted?Et.from:Et.to,n=Kt(t.line),r=t.ch-1,i=r>=0&&Br[n.text.charAt(r)]||Br[n.text.charAt(++r)];if(!i)return;var s=i.charAt(0),o=i.charAt(1)==">",u=o?1:-1,a=n.styles;for(var f=r+1,l=0,c=a.length;l<c;l+=2)if((f-=a[l].length)<=0){var h=a[l+1];break}var p=[n.text.charAt(r)],d=/[(){}[\]]/;for(var l=t.line,c=o?Math.min(l+100,yt.size):Math.max(-1,l-100);l!=c;l+=u){var n=Kt(l),m=l==t.line,g=v(n,m&&o?r+1:0,m&&!o?r:n.text.length);if(g)break}g||(g={pos:null,match:!1});var h=g.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",y=ar({line:t.line,ch:r},{line:t.line,ch:r+1},h),b=g.pos!=null&&ar({line:l,ch:g.pos},{line:l,ch:g.pos+1},h),w=Vr(function(){y.clear(),b&&b.clear()});e?setTimeout(w,800):Rt=w}function Fr(e){var t,n;for(var r=e,i=e-40;r>i;--r){if(r==0)return 0;var o=Kt(r-1);if(o.stateAfter)return r;var u=o.indentation(s.tabSize);if(n==null||t>u)n=r-1,t=u}return n}function Ir(e){var t=Fr(e),n=t&&Kt(t-1).stateAfter;return n?n=h(gt,n):n=p(gt),yt.iter(t,e,function(e){e.highlight(gt,n,s.tabSize),e.stateAfter=h(gt,n)}),t<e&&Mt.push({from:t,to:e}),e<yt.size&&!Kt(e).stateAfter&&bt.push(e),n}function qr(e,t){var n=Ir(e);yt.iter(e,t,function(e){e.highlight(gt,n,s.tabSize),e.stateAfter=h(gt,n)})}function Rr(){var e=+(new Date)+s.workTime,t=bt.length;while(bt.length){if(!Kt(Ft).stateAfter)var n=Ft;else var n=bt.pop();if(n>=yt.size)continue;var r=Fr(n),i=r&&Kt(r-1).stateAfter;i?i=h(gt,i):i=p(gt);var o=0,u=gt.compareStates,a=!1,f=r,l=!1;yt.iter(f,yt.size,function(t){var r=t.stateAfter;if(+(new Date)>e)return bt.push(f),Ur(s.workDelay),a&&Mt.push({from:n,to:f+1}),l=!0;var c=t.highlight(gt,i,s.tabSize);c&&(a=!0),t.stateAfter=h(gt,i);if(u){if(r&&u(r,i))return!0}else if(c!==!1||!r)o=0;else if(++o>3&&(!gt.indent||gt.indent(r,"")==gt.indent(i,"")))return!0;++f});if(l)return;a&&Mt.push({from:n,to:f+1})}t&&s.onHighlightComplete&&s.onHighlightComplete(Jt)}function Ur(e){if(!bt.length)return;vt.set(e,Vr(Rr))}function zr(){At=Ot=_t=null,Mt=[],Dt=!1,Bt=[]}function Wr(){var e=!1,t;Dt&&(e=!_n()),Mt.length?t=Hn(Mt,!0):(Dt&&In(),Ht&&Fn()),e&&_n(),Dt&&(Mn(),Hr()),wt&&!Pt&&(At===!0||At!==!1&&Dt)&&An(Ot),Dt&&s.matchBrackets&&setTimeout(Vr(function(){Rt&&(Rt(),Rt=null),Q(Et.from,Et.to)&&jr(!1)}),20);var n=_t,r=Bt;Dt&&s.onCursorActivity&&s.onCursorActivity(Jt),n&&s.onChange&&Jt&&s.onChange(Jt,n);for(var i=0;i<r.length;++i)r[i](Jt);t&&s.onUpdate&&s.onUpdate(Jt)}function Vr(e){return function(){Xr++||zr();try{var t=e.apply(this,arguments)}finally{--Xr||Wr()}return t}}var s={},a=e.defaults;for(var d in a)a.hasOwnProperty(d)&&(s[d]=(i&&i.hasOwnProperty(d)?i:a)[d]);var y=document.createElement("div");y.className="CodeMirror"+(s.lineWrapping?" CodeMirror-wrap":""),y.innerHTML='<div style="overflow: hidden; position: relative; width: 3px; height: 0px;"><textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" autocorrect="off" autocapitalize="off"></textarea></div><div class="CodeMirror-scroll" tabindex="-1"><div style="position: relative"><div style="position: relative"><div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div><div class="CodeMirror-lines"><div style="position: relative; z-index: 0"><div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;"></div><pre class="CodeMirror-cursor"> </pre><div style="position: relative; z-index: -1"></div><div></div></div></div></div></div></div>',r.appendChild?r.appendChild(y):r(y);var C=y.firstChild,A=C.firstChild,W=y.lastChild,X=W.firstChild,V=X.firstChild,Z=V.firstChild,ut=Z.firstChild,at=Z.nextSibling.firstChild,ft=at.firstChild,lt=ft.nextSibling,ct=lt.nextSibling,ht=ct.nextSibling;or(),t&&(A.style.width="0px"),q||(at.draggable=!0),at.style.outline="none",s.tabindex!=null&&(A.tabIndex=s.tabindex),s.autofocus&&On(),!s.gutter&&!s.lineNumbers&&(Z.style.display="none"),U&&(C.style.height="1px",C.style.position="absolute");try{gr("x")}catch(pt){throw pt.message.match(/runtime/i)&&(pt=new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)")),pt}var dt=new H,vt=new H,mt,gt,yt=new w([new b([new g("")])]),bt,wt;nr();var Et={from:{line:0,ch:0},to:{line:0,ch:0},inverted:!1},St,xt,Tt,Nt=0,Ct,kt=!1,Lt=!1,At,Ot,Mt,_t,Dt,Pt,Ht,Bt,jt=0,Ft=0,It=0,qt=0,Rt,Ut="",zt,Wt={};Vr(function(){Gt(s.value||""),At=!1})();var Xt=new N;P(W,"mousedown",Vr(Zt)),P(W,"dblclick",Vr(en)),P(at,"dragstart",nn),P(at,"selectstart",L),j||P(W,"contextmenu",Pr),P(W,"scroll",function(){Nt=W.scrollTop,Hn([]),s.fixedGutter&&(Z.style.left=W.scrollLeft+"px"),s.onScroll&&s.onScroll(Jt)}),P(window,"resize",function(){Hn(!0)}),P(A,"keyup",Vr(cn)),P(A,"input",Cn),P(A,"keydown",Vr(fn)),P(A,"keypress",Vr(ln)),P(A,"focus",hn),P(A,"blur",pn),P(W,"dragenter",O),P(W,"dragover",O),P(W,"drop",Vr(tn)),P(W,"paste",function(){On(),Cn()}),P(A,"paste",Cn),P(A,"cut",Vr(function(){s.readOnly||wn("")})),U&&P(X,"mouseup",function(){document.activeElement==A&&A.blur(),On()});var Vt;try{Vt=document.activeElement==A}catch(pt){}Vt||s.autofocus?setTimeout(hn,20):pn();var Jt=y.CodeMirror={getValue:Yt,setValue:Vr(Gt),getSelection:xn,replaceSelection:Vr(wn),focus:function(){window.focus(),On(),hn(),Cn()},setOption:function(e,t){var n=s[e];s[e]=t,e=="mode"||e=="indentUnit"?nr():e=="readOnly"&&t=="nocursor"?(pn(),A.blur()):e=="readOnly"&&!t?An(!0):e=="theme"?or():e=="lineWrapping"&&n!=t?Vr(ir)():e=="tabSize"&&Hn(!0);if(e=="lineNumbers"||e=="gutter"||e=="firstLineNumber"||e=="theme")rr(),Hn(!0)},getOption:function(e){return s[e]},undo:Vr(mn),redo:Vr(gn),indentLine:Vr(function(e,t){typeof t!="string"&&(t==null?t=s.smartIndent?"smart":"prev":t=t?"add":"subtract"),$t(e)&&tr(e,t)}),indentSelection:Vr(er),historySize:function(){return{undo:Xt.done.length,redo:Xt.undone.length}},clearHistory:function(){Xt=new N},matchBrackets:Vr(function(){jr(!0)}),getTokenAt:Vr(function(e){return e=Vn(e),Kt(e.line).getTokenAt(gt,Ir(e.line),e.ch)}),getStateAfter:function(e){return e=Xn(e==null?yt.size-1:e),Ir(e+1)},cursorCoords:function(e,t){return e==null&&(e=Et.inverted),this.charCoords(e?Et.from:Et.to,t)},charCoords:function(e,t){return e=Vn(e),t=="local"?Er(e,!1):t=="div"?Er(e,!0):xr(e)},coordsChar:function(e){var t=$(at);return Sr(e.x-t.left,e.y-t.top)},markText:Vr(ar),setBookmark:fr,findMarksAt:lr,setMarker:Vr(cr),clearMarker:Vr(hr),setLineClass:Vr(dr),hideLine:Vr(function(e){return vr(e,!0)}),showLine:Vr(function(e){return vr(e,!1)}),onDeleteLine:function(e,t){if(typeof e=="number"){if(!$t(e))return null;e=Kt(e)}return(e.handlers||(e.handlers=[])).push(t),e},lineInfo:mr,addWidget:function(e,t,n,r,i){e=Er(Vn(e));var s=e.yBot,o=e.x;t.style.position="absolute",X.appendChild(t);if(r=="over")s=e.y;else if(r=="near"){var u=Math.max(W.offsetHeight,yt.height*kr()),a=Math.max(X.clientWidth,at.clientWidth)-_r();e.yBot+t.offsetHeight>u&&e.y>t.offsetHeight&&(s=e.y-t.offsetHeight),o+t.offsetWidth>a&&(o=a-t.offsetWidth)}t.style.top=s+Mr()+"px",t.style.left=t.style.right="",i=="right"?(o=X.clientWidth-t.offsetWidth,t.style.right="0px"):(i=="left"?o=0:i=="middle"&&(o=(X.clientWidth-t.offsetWidth)/2),t.style.left=o+_r()+"px"),n&&Dn(o,s,o+t.offsetWidth,s+t.offsetHeight)},lineCount:function(){return yt.size},clipPos:Vn,getCursor:function(e){return e==null&&(e=Et.inverted),Y(e?Et.from:Et.to)},somethingSelected:function(){return!Q(Et.from,Et.to)},setCursor:Vr(function(e,t,n){t==null&&typeof e.line=="number"?Wn(e.line,e.ch,n):Wn(e,t,n)}),setSelection:Vr(function(e,t,n){(n?Rn:Un)(Vn(e),Vn(t||e))}),getLine:function(e){if($t(e))return Kt(e).text},getLineHandle:function(e){if($t(e))return Kt(e)},setLine:Vr(function(e,t){$t(e)&&bn(t,{line:e,ch:0},{line:e,ch:Kt(e).text.length})}),removeLine:Vr(function(e){$t(e)&&bn("",{line:e,ch:0},Vn({line:e+1,ch:0}))}),replaceRange:Vr(bn),getRange:function(e,t){return Sn(Vn(e),Vn(t))},triggerOnKeyDown:Vr(fn),execCommand:function(e){return u[e](Jt)},moveH:Vr(Jn),deleteH:Vr(Kn),moveV:Vr(Gn),toggleOverwrite:function(){kt?(kt=!1,lt.className=lt.className.replace(" CodeMirror-overwrite","")):(kt=!0,lt.className+=" CodeMirror-overwrite")},posFromIndex:function(e){var t=0,n;return yt.iter(0,yt.size,function(r){var i=r.text.length+1;if(i>e)return n=e,!0;e-=i,++t}),Vn({line:t,ch:n})},indexFromPos:function(e){if(e.line<0||e.ch<0)return 0;var t=e.ch;return yt.iter(0,e.line,function(e){t+=e.text.length+1}),t},scrollTo:function(e,t){e!=null&&(W.scrollLeft=e),t!=null&&(W.scrollTop=t),Hn([])},operation:function(e){return Vr(e)()},refresh:function(){Hn(!0),W.scrollHeight>Nt&&(W.scrollTop=Nt)},getInputField:function(){return A},getWrapperElement:function(){return y},getScrollerElement:function(){return W},getGutterElement:function(){return Z}},un=null,an,Tn=!1,kn="",Qn=null;ur.prototype.clear=Vr(function(){var e=Infinity,t=-Infinity;for(var n=0,r=this.set.length;n<r;++n){var i=this.set[n],s=i.marked;if(!s||!i.parent)continue;var o=S(i);e=Math.min(e,o),t=Math.max(t,o);for(var u=0;u<s.length;++u)s[u].marker==this&&s.splice(u--,1)}e!=Infinity&&Mt.push({from:e,to:t+1})}),ur.prototype.find=function(){var e,t;for(var n=0,r=this.set.length;n<r;++n){var i=this.set[n],s=i.marked;for(var o=0;o<s.length;++o){var u=s[o];if(u.marker==this)if(u.from!=null||u.to!=null){var a=S(i);a!=null&&(u.from!=null&&(e={line:a,ch:u.from}),u.to!=null&&(t={line:a,ch:u.to}))}}}return{from:e,to
:t}};var br=Math.floor(Math.random()*16777215).toString(16),Tr,Nr,Cr,Lr,Ar=0,Br={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},Xr=0;for(var $r in o)o.propertyIsEnumerable($r)&&!Jt.propertyIsEnumerable($r)&&(Jt[$r]=o[$r]);return Jt}function f(e){return typeof e=="string"?a[e]:e}function l(e,t,n,r){function i(t){t=f(t);var n=t[e];if(n!=null&&r(n))return!0;if(t.catchall)return r(t.catchall);var s=t.fallthrough;if(s==null)return!1;if(Object.prototype.toString.call(s)!="[object Array]")return i(s);for(var o=0,u=s.length;o<u;++o)if(i(s[o]))return!0;return!1}return t&&i(t)?!0:i(n)}function c(e){var t=ot[D(e,"keyCode")];return t=="Ctrl"||t=="Alt"||t=="Shift"||t=="Mod"}function h(e,t){if(t===!0)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function p(e,t,n){return e.startState?e.startState(t,n):!0}function d(e,t){this.pos=this.start=0,this.string=e,this.tabSize=t||8}function v(e,t,n,r){this.from=e,this.to=t,this.style=n,this.marker=r}function m(e){this.from=e,this.to=e,this.line=null}function g(e,t){this.styles=t||[e,null],this.text=e,this.height=1,this.marked=this.gutterMarker=this.className=this.bgClassName=this.handlers=null,this.stateAfter=this.parent=this.hidden=null}function y(e,t,n,r){for(var i=0,s=0,o=0;s<t;i+=2){var u=n[i],a=s+u.length;o==0?(a>e&&r.push(u.slice(e-s,Math.min(u.length,t-s)),n[i+1]),a>=e&&(o=1)):o==1&&(a>t?r.push(u.slice(0,t-s),n[i+1]):r.push(u,n[i+1])),s=a}}function b(e){this.lines=e,this.parent=null;for(var t=0,n=e.length,r=0;t<n;++t)e[t].parent=this,r+=e[t].height;this.height=r}function w(e){this.children=e;var t=0,n=0;for(var r=0,i=e.length;r<i;++r){var s=e[r];t+=s.chunkSize(),n+=s.height,s.parent=this}this.size=t,this.height=n,this.parent=null}function E(e,t){while(!e.lines)for(var n=0;;++n){var r=e.children[n],i=r.chunkSize();if(t<i){e=r;break}t-=i}return e.lines[t]}function S(e){if(e.parent==null)return null;var t=e.parent,n=nt(t.lines,e);for(var r=t.parent;r;t=r,r=r.parent)for(var i=0,s=r.children.length;;++i){if(r.children[i]==t)break;n+=r.children[i].chunkSize()}return n}function x(e,t){var n=0;e:do{for(var r=0,i=e.children.length;r<i;++r){var s=e.children[r],o=s.height;if(t<o){e=s;continue e}t-=o,n+=s.chunkSize()}return n}while(!e.lines);for(var r=0,i=e.lines.length;r<i;++r){var u=e.lines[r],a=u.height;if(t<a)break;t-=a}return n+r}function T(e,t){var n=0;e:do{for(var r=0,i=e.children.length;r<i;++r){var s=e.children[r],o=s.chunkSize();if(t<o){e=s;continue e}t-=o,n+=s.height}return n}while(!e.lines);for(var r=0;r<t;++r)n+=e.lines[r].height;return n}function N(){this.time=0,this.done=[],this.undone=[]}function C(){O(this)}function k(e){return e.stop||(e.stop=C),e}function L(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function A(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function O(e){L(e),A(e)}function M(e){return e.target||e.srcElement}function _(e){if(e.which)return e.which;if(e.button&1)return 1;if(e.button&2)return 3;if(e.button&4)return 2}function D(e,t){var n=e.override&&e.override.hasOwnProperty(t);return n?e.override[t]:e[t]}function P(e,t,n,r){if(typeof e.addEventListener=="function"){e.addEventListener(t,n,!1);if(r)return function(){e.removeEventListener(t,n,!1)}}else{var i=function(e){n(e||window.event)};e.attachEvent("on"+t,i);if(r)return function(){e.detachEvent("on"+t,i)}}}function H(){this.id=null}function X(e,t,n){t==null&&(t=e.search(/[^\s\u00a0]/),t==-1&&(t=e.length));for(var r=0,i=0;r<t;++r)e.charAt(r)==" "?i+=n-i%n:++i;return i}function V(e){return e.currentStyle?e.currentStyle:window.getComputedStyle(e,null)}function $(e,t){var n=e.ownerDocument.body,r=0,i=0,s=!1;for(var o=e;o;o=o.offsetParent){var u=o.offsetLeft,a=o.offsetTop;o==n?(r+=Math.abs(u),i+=Math.abs(a)):(r+=u,i+=a),t&&V(o).position=="fixed"&&(s=!0)}var f=t&&!s?null:n;for(var o=e.parentNode;o!=f;o=o.parentNode)o.scrollLeft!=null&&(r-=o.scrollLeft,i-=o.scrollTop);return{left:r,top:i}}function J(e){return e.textContent||e.innerText||e.nodeValue||""}function K(e){t?(e.selectionStart=0,e.selectionEnd=e.value.length):e.select()}function Q(e,t){return e.line==t.line&&e.ch==t.ch}function G(e,t){return e.line<t.line||e.line==t.line&&e.ch<t.ch}function Y(e){return{line:e.line,ch:e.ch}}function et(e){return Z.textContent=e,Z.innerHTML}function tt(e,t){if(!t)return 0;if(!e)return t.length;for(var n=e.length,r=t.length;n>=0&&r>=0;--n,--r)if(e.charAt(n)!=t.charAt(r))break;return r+1}function nt(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n<r;++n)if(e[n]==t)return n;return-1}function rt(e){return/\w/.test(e)||e.toUpperCase()!=e.toLowerCase()}e.defaults={value:"",mode:null,theme:"default",indentUnit:2,indentWithTabs:!1,smartIndent:!0,tabSize:4,keyMap:"default",extraKeys:null,electricChars:!0,autoClearEmptyLines:!1,onKeyEvent:null,lineWrapping:!1,lineNumbers:!1,gutter:!1,fixedGutter:!1,firstLineNumber:1,readOnly:!1,onChange:null,onCursorActivity:null,onGutterClick:null,onHighlightComplete:null,onUpdate:null,onFocus:null,onBlur:null,onScroll:null,matchBrackets:!1,workTime:100,workDelay:200,pollInterval:100,undoDepth:40,tabindex:null,autofocus:null};var t=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),n=t||/Mac/.test(navigator.platform),r=/Win/.test(navigator.platform),i=e.modes={},s=e.mimeModes={};e.defineMode=function(t,n){!e.defaults.mode&&t!="null"&&(e.defaults.mode=t),i[t]=n},e.defineMIME=function(e,t){s[e]=t},e.resolveMode=function(t){if(typeof t=="string"&&s.hasOwnProperty(t))t=s[t];else if(typeof t=="string"&&/^[\w\-]+\/[\w\-]+\+xml$/.test(t))return e.resolveMode("application/xml");return typeof t=="string"?{name:t}:t||{name:"null"}},e.getMode=function(t,n){var n=e.resolveMode(n),r=i[n.name];return r?r(t,n):(window.console&&console.warn("No mode "+n.name+" found, falling back to plain text."),e.getMode(t,"text/plain"))},e.listModes=function(){var e=[];for(var t in i)i.propertyIsEnumerable(t)&&e.push(t);return e},e.listMIMEs=function(){var e=[];for(var t in s)s.propertyIsEnumerable(t)&&e.push({mime:t,mode:s[t]});return e};var o=e.extensions={};e.defineExtension=function(e,t){o[e]=t};var u=e.commands={selectAll:function(e){e.setSelection({line:0,ch:0},{line:e.lineCount()-1})},killLine:function(e){var t=e.getCursor(!0),n=e.getCursor(!1),r=!Q(t,n);!r&&e.getLine(t.line).length==t.ch?e.replaceRange("",t,{line:t.line+1,ch:0}):e.replaceRange("",t,r?n:{line:t.line})},deleteLine:function(e){var t=e.getCursor().line;e.replaceRange("",{line:t,ch:0},{line:t})},undo:function(e){e.undo()},redo:function(e){e.redo()},goDocStart:function(e){e.setCursor(0,0,!0)},goDocEnd:function(e){e.setSelection({line:e.lineCount()-1},null,!0)},goLineStart:function(e){e.setCursor(e.getCursor().line,0,!0)},goLineStartSmart:function(e){var t=e.getCursor(),n=e.getLine(t.line),r=Math.max(0,n.search(/\S/));e.setCursor(t.line,t.ch<=r&&t.ch?0:r,!0)},goLineEnd:function(e){e.setSelection({line:e.getCursor().line},null,!0)},goLineUp:function(e){e.moveV(-1,"line")},goLineDown:function(e){e.moveV(1,"line")},goPageUp:function(e){e.moveV(-1,"page")},goPageDown:function(e){e.moveV(1,"page")},goCharLeft:function(e){e.moveH(-1,"char")},goCharRight:function(e){e.moveH(1,"char")},goColumnLeft:function(e){e.moveH(-1,"column")},goColumnRight:function(e){e.moveH(1,"column")},goWordLeft:function(e){e.moveH(-1,"word")},goWordRight:function(e){e.moveH(1,"word")},delCharLeft:function(e){e.deleteH(-1,"char")},delCharRight:function(e){e.deleteH(1,"char")},delWordLeft:function(e){e.deleteH(-1,"word")},delWordRight:function(e){e.deleteH(1,"word")},indentAuto:function(e){e.indentSelection("smart")},indentMore:function(e){e.indentSelection("add")},indentLess:function(e){e.indentSelection("subtract")},insertTab:function(e){e.replaceSelection(" ","end")},transposeChars:function(e){var t=e.getCursor(),n=e.getLine(t.line);t.ch>0&&t.ch<n.length-1&&e.replaceRange(n.charAt(t.ch)+n.charAt(t.ch-1),{line:t.line,ch:t.ch-1},{line:t.line,ch:t.ch+1})},newlineAndIndent:function(e){e.replaceSelection("\n","end"),e.indentLine(e.getCursor().line)},toggleOverwrite:function(e){e.toggleOverwrite()}},a=e.keyMap={};a.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharRight",Backspace:"delCharLeft",Tab:"insertTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite"},a.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Alt-Up":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Down":"goDocEnd","Ctrl-Left":"goWordLeft","Ctrl-Right":"goWordRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delWordLeft","Ctrl-Delete":"delWordRight","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore",fallthrough:"basic"},a.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goWordLeft","Alt-Right":"goWordRight","Cmd-Left":"goLineStart","Cmd-Right":"goLineEnd","Alt-Backspace":"delWordLeft","Ctrl-Alt-Backspace":"delWordRight","Alt-Delete":"delWordRight","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore",fallthrough:["basic","emacsy"]},a["default"]=n?a.macDefault:a.pcDefault,a.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageUp","Shift-Ctrl-V":"goPageDown","Ctrl-D":"delCharRight","Ctrl-H":"delCharLeft","Alt-D":"delWordRight","Alt-Backspace":"delWordLeft","Ctrl-K":"killLine","Ctrl-T":"transposeChars"},e.fromTextArea=function(t,n){function r(){t.value=u.getValue()}n||(n={}),n.value=t.value,!n.tabindex&&t.tabindex&&(n.tabindex=t.tabindex),n.autofocus==null&&t.getAttribute("autofocus")!=null&&(n.autofocus=!0);if(t.form){var i=P(t.form,"submit",r,!0);if(typeof t.form.submit=="function"){var s=t.form.submit;function o(){r(),t.form.submit=s,t.form.submit(),t.form.submit=o}t.form.submit=o}}t.style.display="none";var u=e(function(e){t.parentNode.insertBefore(e,t.nextSibling)},n);return u.save=r,u.getTextArea=function(){return t},u.toTextArea=function(){r(),t.parentNode.removeChild(u.getWrapperElement()),t.style.display="",t.form&&(i(),typeof t.form.submit=="function"&&(t.form.submit=s))},u},e.copyState=h,e.startState=p,d.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==0},peek:function(){return this.string.charAt(this.pos)},next:function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},eat:function(e){var t=this.string.charAt(this.pos);if(typeof e=="string")var n=t==e;else var n=t&&(e.test?e.test(t):e(t));if(n)return++this.pos,t},eatWhile:function(e){var t=this.pos;while(this.eat(e));return this.pos>t},eatSpace:function(){var e=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos)))++this.pos;return this.pos>e},skipToEnd:function(){this.pos=this.string.length},skipTo:function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},backUp:function(e){this.pos-=e},column:function(){return X(this.string,this.start,this.tabSize)},indentation:function(){return X(this.string,null,this.tabSize)},match:function(e,t,n){if(typeof e!="string"){var i=this.string.slice(this.pos).match(e);return i&&t!==!1&&(this.pos+=i[0].length),i}function r(e){return n?e.toLowerCase():e}if(r(this.string).indexOf(r(e),this.pos)==this.pos)return t!==!1&&(this.pos+=e.length),!0},current:function(){return this.string.slice(this.start,this.pos)}},e.StringStream=d,v.prototype={attach:function(e){this.marker.set.push(e)},detach:function(e){var t=nt(this.marker.set,e);t>-1&&this.marker.set.splice(t,1)},split:function(e,t){if(this.to<=e&&this.to!=null)return null;var n=this.from<e||this.from==null?null:this.from-e+t,r=this.to==null?null:this.to-e+t;return new v(n,r,this.style,this.marker)},dup:function(){return new v(null,null,this.style,this.marker)},clipTo:function(e,t,n,r,i){e&&r>this.from&&(r<this.to||this.to==null)?this.from=null:this.from!=null&&this.from>=t&&(this.from=Math.max(r,this.from)+i),n&&(t<this.to||this.to==null)&&(t>this.from||this.from==null)?this.to=null:this.to!=null&&this.to>t&&(this.to=r<this.to?this.to+i:t)},isDead:function(){return this.from!=null&&this.to!=null&&this.from>=this.to},sameSet:function(e){return this.marker==e.marker}},m.prototype={attach:function(e){this.line=e},detach:function(e){this.line==e&&(this.line=null)},split:function(e,t){if(e<this.from)return this.from=this.to=this.from-e+t,this},isDead:function(){return this.from>this.to},clipTo:function(e,t,n,r,i){(e||t<this.from)&&(n||r>this.to)?(this.from=0,this.to=-1):this.from>t&&(this.from=this.to=Math.max(r,this.from)+i)},sameSet:function(e){return!1},find:function(){return!this.line||!this.line.parent?null:{line:S(this.line),ch:this.from}},clear:function(){if(this.line){var e=nt(this.line.marked,this);e!=-1&&this.line.marked.splice(e,1),this.line=null}}},g.inheritMarks=function(e,t){var n=new g(e),r=t&&t.marked;if(r)for(var i=0;i<r.length;++i)if(r[i].to==null&&r[i].style){var s=n.marked||(n.marked=[]),o=r[i],u=o.dup();s.push(u),u.attach(n)}return n},g.prototype={replace:function(e,t,n){var r=[],i=this.marked,s=t==null?this.text.length:t;y(0,e,this.styles,r),n&&r.push(n,null),y(s,this.text.length,this.styles,r),this.styles=r,this.text=this.text.slice(0,e)+n+this.text.slice(s),this.stateAfter=null;if(i){var o=n.length-(s-e);for(var u=0;u<i.length;++u){var a=i[u];a.clipTo(e==null,e||0,t==null,s,o),a.isDead()&&(a.detach(this),i.splice(u--,1))}}},split:function(e,t){var n=[t,null],r=this.marked;y(e,this.text.length,this.styles,n);var i=new g(t+this.text.slice(e),n);if(r)for(var s=0;s<r.length;++s){var o=r[s],u=o.split(e,t.length);u&&(i.marked||(i.marked=[]),i.marked.push(u),u.attach(i),u==o&&r.splice(s--,1))}return i},append:function(e){var t=this.text.length,n=e.marked,r=this.marked;this.text+=e.text,y(0,e.text.length,e.styles,this.styles);if(r)for(var i=0;i<r.length;++i)r[i].to==null&&(r[i].to=t);if(n&&n.length){r||(this.marked=r=[]);e:for(var i=0;i<n.length;++i){var s=n[i];if(!s.from)for(var o=0;o<r.length;++o){var u=r[o];if(u.to==t&&u.sameSet(s)){u.to=s.to==null?null:s.to+t,u.isDead()&&(u.detach(this),n.splice(i--,1));continue e}}r.push(s),s.attach(this),s.from+=t,s.to!=null&&(s.to+=t)}}},fixMarkEnds:function(e){var t=this.marked,n=e.marked;if(!t)return;for(var r=0;r<t.length;++r){var i=t[r],s=i.to==null;if(s&&n)for(var o=0;o<n.length;++o)if(n[o].sameSet(i)){s=!1;break}s&&(i.to=this.text.length)}},fixMarkStarts:function(){var e=this.marked;if(!e)return;for(var t=0;t<e.length;++t)e[t].from==null&&(e[t].from=0)},addMark:function(e){e.attach(this),this.marked==null&&(this.marked=[]),this.marked.push(e),this.marked.sort(function(e,t){return(e.from||0)-(t.from||0)})},highlight:function(e,t,n){var r=new d(this.text,n),i=this.styles,s=0,o=!1,u=i[0],a;this.text==""&&e.blankLine&&e.blankLine(t);while(!r.eol()){var f=e.token(r,t),l=this.text.slice(r.start,r.pos);r.start=r.pos,s&&i[s-1]==f?i[s-2]+=l:l&&(!o&&(i[s+1]!=f||s&&i[s-2]!=a)&&(o=!0),i[s++]=l,i[s++]=f,a=u,u=i[s]);if(r.pos>5e3){i[s++]=this.text.slice(r.pos),i[s++]=null;break}}return i.length!=s&&(i.length=s,o=!0),s&&i[s-2]!=a&&(o=!0),o||(i.length<5&&this.text.length<10?null:!1)},getTokenAt:function(e,t,n){var r=this.text,i=new d(r);while(i.pos<n&&!i.eol()){i.start=i.pos;var s=e.token(i,t)}return{start:i.start,end:i.pos,string:i.current(),className:s||null,state:t}},indentation:function(e){return X(this.text,null,e)},getHTML:function(e,t){function s(t,s){if(!t)return;r&&F&&t.charAt(0)==" "&&(t="\u00a0"+t.slice(1)),r=!1;if(t.indexOf(" ")==-1){i+=t.length;var o=et(t)}else{var o="";for(var u=0;;){var a=t.indexOf(" ",u);if(a==-1){o+=et(t.slice(u)),i+=t.length-u;break}i+=a-u;var f=e(i);o+=et(t.slice(u,a))+f.html,i+=f.width,u=a+1}}s?n.push('<span class="',s,'">',o,"</span>"):n.push(o)}function l(e){return e?"cm-"+e.replace(/ +/g," cm-"):null}var n=[],r=!0,i=0,o=this.styles,u=this.text,a=this.marked,f=u.length;t!=null&&(f=Math.min(t,f));if(!u&&t==null)s(" ");else if(!a||!a.length)for(var c=0,h=0;h<f;c+=2){var p=o[c],d=o[c+1],v=p.length;h+v>f&&(p=p.slice(0,f-h)),h+=v,s(p,l(d))}else{var m=0,c=0,g="",d,y=0,b=a[0].from||0,w=[],E=0;function S(){var e;while(E<a.length&&((e=a[E]).from==m||e.from==null))e.style!=null&&w.push(e),++E;b=E<a.length?a[E].from:Infinity;for(var t=0;t<w.length;++t){var n=w[t].to||Infinity;n==m?w.splice(t--,1):b=Math.min(n,b)}}var x=0;while(m<f){b==m&&S();var T=Math.min(f,b);for(;;){if(g){var N=m+g.length,C=d;for(var k=0;k<w.length;++k)C=(C?C+" ":"")+w[k].style;s(N>T?g.slice(0,T-m):g,C);if(N>=T){g=g.slice(T-m),m=T;break}m=N}g=o[c++],d=l(o[c++])}}}return n.join("")},cleanUp:function(){this.parent=null;if(this.marked)for(var e=0,t=this.marked.length;e<t;++e)this.marked[e].detach(this)}},b.prototype={chunkSize:function(){return this.lines.length},remove:function(e,t,n){for(var r=e,i=e+t;r<i;++r){var s=this.lines[r];this.height-=s.height,s.cleanUp();if(s.handlers)for(var o=0;o<s.handlers.length;++o)n.push(s.handlers[o])}this.lines.splice(e,t)},collapse:function(e){e.splice.apply(e,[e.length,0].concat(this.lines))},insertHeight:function(e,t,n){this.height+=n,this.lines.splice.apply(this.lines,[e,0].concat(t));for(var r=0,i=t.length;r<i;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},w.prototype={chunkSize:function(){return this.size},remove:function(e,t,n){this.size-=t;for(var r=0;r<this.children.length;++r){var i=this.children[r],s=i.chunkSize();if(e<s){var o=Math.min(t,s-e),u=i.height;i.remove(e,o,n),this.height-=u-i.height,s==o&&(this.children.splice(r--,1),i.parent=null);if((t-=o)==0)break;e=0}else e-=s}if(this.size-t<25){var a=[];this.collapse(a),this.children=[new b(a)],this.children[0].parent=this}},collapse:function(e){for(var t=0,n=this.children.length;t<n;++t)this.children[t].collapse(e)},insert:function(e,t){var n=0;for(var r=0,i=t.length;r<i;++r)n+=t[r].height;this.insertHeight(e,t,n)},insertHeight:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0,i=this.children.length;r<i;++r){var s=this.children[r],o=s.chunkSize();if(e<=o){s.insertHeight(e,t,n);if(s.lines&&s.lines.length>50){while(s.lines.length>50){var u=s.lines.splice(s.lines.length-25,25),a=new b(u);s.height-=a.height,this.children.splice(r+1,0,a),a.parent=this}this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(this.children.length<=10)return;var e=this;do{var t=e.children.splice(e.children.length-5,5),n=new w(t);if(!e.parent){var r=new w(e.children);r.parent=e,e.children=[r,n],e=r}else{e.size-=n.size,e.height-=n.height;var i=nt(e.parent.children,e);e.parent.children.splice(i+1,0,n)}n.parent=e.parent}while(e.children.length>10);e.parent.maybeSpill()},iter:function(e,t,n){this.iterN(e,t-e,n)},iterN:function(e,t,n){for(var r=0,i=this.children.length;r<i;++r){var s=this.children[r],o=s.chunkSize();if(e<o){var u=Math.min(t,o-e);if(s.iterN(e,u,n))return!0;if((t-=u)==0)break;e=0}else e-=o}}},N.prototype={addChange:function(e,t,n){this.undone.length=0;var r=+(new Date),i=this.done[this.done.length-1],s=i&&i[i.length-1],o=r-this.time;if(o>400||!s)this.done.push([{start:e,added:t,old:n}]);else if(s.start>e+n.length||s.start+s.added<e-s.added+s.old.length)i.push({start:e,added:t,old:n});else{var u=0;if(e<s.start){for(var a=s.start-e-1;a>=0;--a)s.old.unshift(n[a]);u=Math.min(0,t-n.length),s.added+=s.start-e+u,s.start=e}else s.start<e&&(u=e-s.start,t+=u);for(var a=s.added-u,f=n.length;a<f;++a)s.old.push(n[a]);s.added<t&&(s.added=t)}this.time=r}},e.e_stop=O,e.e_preventDefault=L,e.e_stopPropagation=A,e.connect=P,H.prototype={set:function(e,t){clearTimeout(this.id),this.id=setTimeout(t,e)}};var B=e.Pass={toString:function(){return"CodeMirror.Pass"}},j=/gecko\/\d{7}/i.test(navigator.userAgent),F=/MSIE \d/.test(navigator.userAgent),I=/MSIE [1-8]\b/.test(navigator.userAgent),q=/WebKit\//.test(navigator.userAgent),R=/Chrome\//.test(navigator.userAgent),U=/KHTML\//.test(navigator.userAgent),z=function(){if(I)return!1;var e=document.createElement("div");return"draggable"in e||"dragDrop"in e}(),W="\n";(function(){var e=document.createElement("textarea");e.value="foo\nbar",e.value.indexOf("\r")>-1&&(W="\r\n")})(),document.documentElement.getBoundingClientRect!=null&&($=function(e,t){try{var n=e.getBoundingClientRect();n={top:n.top,left:n.left}}catch(r){n={top:0,left:0}}if(!t)if(window.pageYOffset==null){var i=document.documentElement||document.body.parentNode;i.scrollTop==null&&(i=document.body),n.top+=i.scrollTop,n.left+=i.scrollLeft}else n.top+=window.pageYOffset,n.left+=window.pageXOffset;return n});var Z=document.createElement("pre");et("a")=="\na"?et=function(e){return Z.textContent=e,Z.innerHTML.slice(1)}:et(" ")!=" "&&(et=function(e){return Z.innerHTML="",Z.appendChild(document.createTextNode(e)),Z.innerHTML}),e.htmlEscape=et;var it="\n\nb".split(/\n/).length!=3?function(e){var t=0,n,r=[];while((n=e.indexOf("\n",t))>-1)r.push(e.slice(t,e.charAt(n-1)=="\r"?n-1:n)),t=n+1;return r.push(e.slice(t)),r}:function(e){return e.split(/\r?\n/)};e.splitLines=it;var st=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(t){return!1}}:function(e){try{var t=e.ownerDocument.selection.createRange()}catch(n){}return!t||t.parentElement()!=e?!1:t.compareEndPoints("StartToEnd",t)!=0};e.defineMode("null",function(){return{token:function(e){e.skipToEnd()}}}),e.defineMIME("text/plain","null");var ot={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",91:"Mod",92:"Mod",93:"Mod",127:"Delete",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};return e.keyNames=ot,function(){for(var e=0;e<10;e++)ot[e+48]=String(e);for(var e=65;e<=90;e++)ot[e]=String.fromCharCode(e);for(var e=1;e<=12;e++)ot[e+111]=ot[e+63235]="F"+e}(),e}();
//}}}
/***
|''Name''|TiddlyWebAdaptor|
|''Description''|adaptor for interacting with TiddlyWeb|
|''Author:''|FND|
|''Contributors''|Chris Dent, Martin Budden|
|''Version''|1.4.10|
|''Status''|stable|
|''Source''|http://svn.tiddlywiki.org/Trunk/association/adaptors/TiddlyWebAdaptor.js|
|''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/|
|''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]|
|''CoreVersion''|2.5|
|''Keywords''|serverSide TiddlyWeb|
!Notes
This plugin includes [[jQuery JSON|http://code.google.com/p/jquery-json/]].
!To Do
* createWorkspace
* document custom/optional context attributes (e.g. filters, query, revision) and tiddler fields (e.g. server.title, origin)
!Code
***/
//{{{
(function($) {
var adaptor = config.adaptors.tiddlyweb = function() {};
adaptor.prototype = new AdaptorBase();
adaptor.serverType = "tiddlyweb";
adaptor.serverLabel = "TiddlyWeb";
adaptor.mimeType = "application/json";
adaptor.parsingErrorMessage = "Error parsing result from server";
adaptor.noBagErrorMessage = "no bag specified for tiddler";
adaptor.locationIDErrorMessage = "no bag or recipe specified for tiddler"; // TODO: rename
// retrieve current status (requires TiddlyWeb status plugin)
adaptor.prototype.getStatus = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/status";
var uri = uriTemplate.format([context.host]);
var req = httpReq("GET", uri, adaptor.getStatusCallback, context,
null, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getStatusCallback = function(status, context, responseText, uri, xhr) {
context.status = responseText ? status : false;
try {
context.statusText = xhr.statusText;
} catch(exc) { // offline (Firefox)
context.status = false;
context.statusText = null;
}
context.httpStatus = xhr.status;
if(context.status) {
context.serverStatus = $.evalJSON(responseText); // XXX: error handling!?
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve a list of workspaces
adaptor.prototype.getWorkspaceList = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.workspaces = [];
var uriTemplate = "%0/recipes"; // XXX: bags?
var uri = uriTemplate.format([context.host]);
var req = httpReq("GET", uri, adaptor.getWorkspaceListCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getWorkspaceListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
try {
var workspaces = $.evalJSON(responseText);
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
context.workspaces = workspaces.map(function(itm) { return { title: itm }; });
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve a list of tiddlers
adaptor.prototype.getTiddlerList = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers%3";
var params = context.filters ? "?" + context.filters : "";
if(context.format) {
params = context.format + params;
}
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), params]);
var req = httpReq("GET", uri, adaptor.getTiddlerListCallback,
context, merge({ accept: adaptor.mimeType }, context.headers), null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.tiddlers = [];
try {
var tiddlers = $.evalJSON(responseText); //# NB: not actual tiddler instances
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
for(var i = 0; i < tiddlers.length; i++) {
var tiddler = adaptor.toTiddler(tiddlers[i], context.host);
context.tiddlers.push(tiddler);
}
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// perform global search
adaptor.prototype.getSearchResults = function(context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/search?q=%1%2";
var filterString = context.filters ? ";" + context.filters : "";
var uri = uriTemplate.format([context.host, context.query, filterString]); // XXX: parameters need escaping?
var req = httpReq("GET", uri, adaptor.getSearchResultsCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getSearchResultsCallback = function(status, context, responseText, uri, xhr) {
adaptor.getTiddlerListCallback(status, context, responseText, uri, xhr); // XXX: use apply?
};
// retrieve a particular tiddler's revisions
adaptor.prototype.getTiddlerRevisionList = function(title, limit, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions";
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title)]);
var req = httpReq("GET", uri, adaptor.getTiddlerRevisionListCallback,
context, merge({ accept: adaptor.mimeType }, context.headers), null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerRevisionListCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.revisions = [];
try {
var tiddlers = $.evalJSON(responseText); //# NB: not actual tiddler instances
} catch(ex) {
context.status = false; // XXX: correct?
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
for(var i = 0; i < tiddlers.length; i++) {
var tiddler = adaptor.toTiddler(tiddlers[i], context.host);
context.revisions.push(tiddler);
}
var sortField = "server.page.revision";
context.revisions.sort(function(a, b) {
return a.fields[sortField] < b.fields[sortField] ? 1 :
(a.fields[sortField] == b.fields[sortField] ? 0 : -1);
});
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve an individual tiddler revision -- XXX: breaks with standard arguments list -- XXX: convenience function; simply use getTiddler?
adaptor.prototype.getTiddlerRevision = function(title, revision, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.revision = revision;
return this.getTiddler(title, context, userParams, callback);
};
// retrieve an individual tiddler
//# context is an object with members host and workspace
//# callback is passed the new context and userParams
adaptor.prototype.getTiddler = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
if(context.revision) {
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions/%4";
} else {
uriTemplate = "%0/%1/%2/tiddlers/%3";
}
if(!context.tiddler) {
context.tiddler = new Tiddler(title);
}
context.tiddler.fields["server.type"] = adaptor.serverType;
context.tiddler.fields["server.host"] = AdaptorBase.minHostName(context.host);
context.tiddler.fields["server.workspace"] = context.workspace;
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title),
context.revision]);
var req = httpReq("GET", uri, adaptor.getTiddlerCallback, context,
merge({ accept: adaptor.mimeType }, context.headers), null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
try {
var tid = $.evalJSON(responseText);
} catch(ex) {
context.status = false;
context.statusText = exceptionText(ex, adaptor.parsingErrorMessage);
if(context.callback) {
context.callback(context, context.userParams);
}
return;
}
var tiddler = adaptor.toTiddler(tid, context.host);
tiddler.title = context.tiddler.title;
tiddler.fields["server.etag"] = xhr.getResponseHeader("Etag");
// normally we'd assign context.tiddler = tiddler here - but we can't do
// that because of IE, which triggers getTiddler in putTiddlerCallback,
// and since ServerSideSavingPlugin foolishly relies on persistent
// object references, we need to merge the data into the existing object
$.extend(context.tiddler, tiddler);
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// retrieve tiddler chronicle (all revisions)
adaptor.prototype.getTiddlerChronicle = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions?fat=1";
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(title)]);
var req = httpReq("GET", uri, adaptor.getTiddlerChronicleCallback,
context, { accept: adaptor.mimeType }, null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerChronicleCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(status) {
context.responseText = responseText;
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// store an individual tiddler
adaptor.prototype.putTiddler = function(tiddler, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = tiddler.title;
context.tiddler = tiddler;
context.host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var uriTemplate = "%0/%1/%2/tiddlers/%3";
try {
context.workspace = context.workspace || tiddler.fields["server.workspace"];
var workspace = adaptor.resolveWorkspace(context.workspace);
} catch(ex) {
return adaptor.locationIDErrorMessage;
}
var uri = uriTemplate.format([context.host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title)]);
var etag = adaptor.generateETag(workspace, tiddler);
var headers = etag ? { "If-Match": etag } : null;
var payload = {
type: tiddler.fields["server.content-type"] || null,
text: tiddler.text,
tags: tiddler.tags,
fields: $.extend({}, tiddler.fields)
};
delete payload.fields.changecount;
$.each(payload.fields, function(key, value) {
if(key.indexOf("server.") == 0) {
delete payload.fields[key];
}
});
payload = $.toJSON(payload);
var req = httpReq("PUT", uri, adaptor.putTiddlerCallback,
context, headers, payload, adaptor.mimeType, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.status) {
var loc = xhr.getResponseHeader("Location");
var etag = xhr.getResponseHeader("Etag");
if(loc && etag) {
var bag = loc.split("/bags/").pop().split("/")[0];
context.tiddler.fields["server.bag"] = bag;
context.tiddler.fields["server.workspace"] = "bags/" + bag;
var rev = etag.split("/").pop().split(/;|:/)[0];
context.tiddler.fields["server.page.revision"] = rev;
context.tiddler.fields["server.etag"] = etag;
if(context.callback) {
context.callback(context, context.userParams);
}
} else { // IE
context.adaptor.getTiddler(context.tiddler.title, context,
context.userParams, context.callback);
}
} else if(context.callback) {
context.callback(context, context.userParams);
}
};
// store a tiddler chronicle
adaptor.prototype.putTiddlerChronicle = function(revisions, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = revisions[0].title;
var headers = null;
var uriTemplate = "%0/%1/%2/tiddlers/%3/revisions";
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(context.title)]);
if(workspace.type == "bag") { // generate ETag
var etag = [adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(context.title), 0].join("/"); //# zero-revision prevents overwriting existing contents
headers = { "If-Match": '"' + etag + '"' };
}
var payload = $.toJSON(revisions);
var req = httpReq("POST", uri, adaptor.putTiddlerChronicleCallback,
context, headers, payload, adaptor.mimeType, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerChronicleCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// store a collection of tiddlers (import TiddlyWiki HTML store)
adaptor.prototype.putTiddlerStore = function(store, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
var uriTemplate = "%0/%1/%2/tiddlers";
var host = context.host;
var workspace = adaptor.resolveWorkspace(context.workspace);
var uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name)]);
var req = httpReq("POST", uri, adaptor.putTiddlerStoreCallback,
context, null, store, "text/x-tiddlywiki", null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.putTiddlerStoreCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// rename an individual tiddler or move it to a different workspace -- TODO: make {from|to}.title optional
//# from and to are objects with members title and workspace (bag; optional),
//# representing source and target tiddler, respectively
adaptor.prototype.moveTiddler = function(from, to, context, userParams, callback) { // XXX: rename parameters (old/new)?
var self = this;
var newTiddler = store.getTiddler(from.title) || store.getTiddler(to.title); //# local rename might already have occurred
var oldTiddler = $.extend(true, {}, newTiddler); //# required for eventual deletion
oldTiddler.title = from.title; //# required for original tiddler's ETag
var _getTiddlerChronicle = function(title, context, userParams, callback) {
return self.getTiddlerChronicle(title, context, userParams, callback);
};
var _putTiddlerChronicle = function(context, userParams) {
if(!context.status) {
return callback(context, userParams);
}
var revisions = $.evalJSON(context.responseText); // XXX: error handling?
// change current title while retaining previous location
for(var i = 0; i < revisions.length; i++) {
delete revisions[i].revision;
if(!revisions[i].fields.origin) { // NB: origin = "<workspace>/<title>"
revisions[i].fields.origin = ["bags", revisions[i].bag, revisions[i].title].join("/");
}
revisions[i].title = to.title;
}
// add new revision
var rev = $.extend({}, revisions[0]);
$.each(newTiddler, function(i, item) {
if(!$.isFunction(item)) {
rev[i] = item;
}
});
rev.title = to.title;
rev.created = rev.created.convertToYYYYMMDDHHMM();
rev.modified = new Date().convertToYYYYMMDDHHMM();
delete rev.fields.changecount;
revisions.unshift(rev);
if(to.workspace) {
context.workspace = to.workspace;
} else if(context.workspace.substring(0, 4) != "bags") { // NB: target workspace must be a bag
context.workspace = "bags/" + rev.bag;
}
var subCallback = function(context, userParams) {
if(!context.status) {
return callback(context, userParams);
}
context.adaptor.getTiddler(newTiddler.title, context, userParams, _deleteTiddler);
};
return self.putTiddlerChronicle(revisions, context, context.userParams, subCallback);
};
var _deleteTiddler = function(context, userParams) {
if(!context.status) {
return callback(context, userParams);
}
$.extend(true, newTiddler, context.tiddler);
context.callback = null;
return self.deleteTiddler(oldTiddler, context, context.userParams, callback);
};
callback = callback || function() {};
context = this.setContext(context, userParams);
context.host = context.host || oldTiddler.fields["server.host"];
context.workspace = from.workspace || oldTiddler.fields["server.workspace"];
return _getTiddlerChronicle(from.title, context, userParams, _putTiddlerChronicle);
};
// delete an individual tiddler
adaptor.prototype.deleteTiddler = function(tiddler, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = tiddler.title; // XXX: not required!?
var uriTemplate = "%0/bags/%1/tiddlers/%2";
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var bag = tiddler.fields["server.bag"];
if(!bag) {
return adaptor.noBagErrorMessage;
}
var uri = uriTemplate.format([host, adaptor.normalizeTitle(bag),
adaptor.normalizeTitle(tiddler.title)]);
var etag = adaptor.generateETag({ type: "bag", name: bag }, tiddler);
var headers = etag ? { "If-Match": etag } : null;
var req = httpReq("DELETE", uri, adaptor.deleteTiddlerCallback, context, headers,
null, null, null, null, true);
return typeof req == "string" ? req : true;
};
adaptor.deleteTiddlerCallback = function(status, context, responseText, uri, xhr) {
context.status = [204, 1223].contains(xhr.status);
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
if(context.callback) {
context.callback(context, context.userParams);
}
};
// compare two revisions of a tiddler (requires TiddlyWeb differ plugin)
//# if context.rev1 is not specified, the latest revision will be used for comparison
//# if context.rev2 is not specified, the local revision will be sent for comparison
//# context.format is a string as determined by the TiddlyWeb differ plugin
adaptor.prototype.getTiddlerDiff = function(title, context, userParams, callback) {
context = this.setContext(context, userParams, callback);
context.title = title;
var tiddler = store.getTiddler(title);
try {
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
} catch(ex) {
return adaptor.locationIDErrorMessage;
}
var tiddlerRef = [workspace.type + "s", workspace.name, tiddler.title].join("/");
var rev1 = context.rev1 ? [tiddlerRef, context.rev1].join("/") : tiddlerRef;
var rev2 = context.rev2 ? [tiddlerRef, context.rev2].join("/") : null;
var uriTemplate = "%0/diff?rev1=%1";
if(rev2) {
uriTemplate += "&rev2=%2";
}
if(context.format) {
uriTemplate += "&format=%3";
}
var host = context.host || this.fullHostName(tiddler.fields["server.host"]);
var uri = uriTemplate.format([host, adaptor.normalizeTitle(rev1),
adaptor.normalizeTitle(rev2), context.format]);
if(rev2) {
var req = httpReq("GET", uri, adaptor.getTiddlerDiffCallback, context, null,
null, null, null, null, true);
} else {
var payload = {
title: tiddler.title,
text: tiddler.text,
modifier: tiddler.modifier,
tags: tiddler.tags,
fields: $.extend({}, tiddler.fields)
}; // XXX: missing attributes!?
payload = $.toJSON(payload);
req = httpReq("POST", uri, adaptor.getTiddlerDiffCallback, context,
null, payload, adaptor.mimeType, null, null, true);
}
return typeof req == "string" ? req : true;
};
adaptor.getTiddlerDiffCallback = function(status, context, responseText, uri, xhr) {
context.status = status;
context.statusText = xhr.statusText;
context.httpStatus = xhr.status;
context.uri = uri;
if(status) {
context.diff = responseText;
}
if(context.callback) {
context.callback(context, context.userParams);
}
};
// generate tiddler information
adaptor.prototype.generateTiddlerInfo = function(tiddler) {
var info = {};
var uriTemplate = "%0/%1/%2/tiddlers/%3";
var host = this.host || tiddler.fields["server.host"]; // XXX: this.host obsolete?
host = this.fullHostName(host);
var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]);
info.uri = uriTemplate.format([host, workspace.type + "s",
adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title)]);
return info;
};
// create Tiddler instance from TiddlyWeb tiddler JSON
adaptor.toTiddler = function(json, host) {
var created = Date.convertFromYYYYMMDDHHMM(json.created);
var modified = Date.convertFromYYYYMMDDHHMM(json.modified);
var fields = json.fields;
fields["server.type"] = adaptor.serverType;
fields["server.host"] = AdaptorBase.minHostName(host);
fields["server.bag"] = json.bag;
fields["server.title"] = json.title;
if(json.recipe) {
fields["server.recipe"] = json.recipe;
}
if(json.type && json.type != "None") {
fields["server.content-type"] = json.type;
}
fields["server.permissions"] = json.permissions.join(", ");
fields["server.page.revision"] = json.revision;
fields["server.workspace"] = "bags/" + json.bag;
var tiddler = new Tiddler(json.title);
tiddler.assign(tiddler.title, json.text, json.modifier, modified, json.tags,
created, json.fields, json.creator);
return tiddler;
};
adaptor.resolveWorkspace = function(workspace) {
var components = workspace.split("/");
return {
type: components[0] == "bags" ? "bag" : "recipe",
name: components[1] || components[0]
};
};
adaptor.generateETag = function(workspace, tiddler) {
var revision = tiddler.fields["server.page.revision"];
var etag = revision == "false" ? null : tiddler.fields["server.etag"];
if(!etag && workspace.type == "bag") {
if(typeof revision == "undefined") {
revision = "0";
} else if(revision == "false") {
return null;
}
etag = [adaptor.normalizeTitle(workspace.name),
adaptor.normalizeTitle(tiddler.title), revision].join("/");
etag = '"' + etag + '"';
}
return etag;
};
adaptor.normalizeTitle = function(title) {
return encodeURIComponent(title);
};
})(jQuery);
/*
* jQuery JSON Plugin
* version: 1.3
* source: http://code.google.com/p/jquery-json/
* license: MIT (http://www.opensource.org/licenses/mit-license.php)
*/
(function($){function toIntegersAtLease(n)
{return n<10?'0'+n:n;}
Date.prototype.toJSON=function(date)
{return this.getUTCFullYear()+'-'+
toIntegersAtLease(this.getUTCMonth())+'-'+
toIntegersAtLease(this.getUTCDate());};var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};$.quoteString=function(string)
{if(escapeable.test(string))
{return'"'+string.replace(escapeable,function(a)
{var c=meta[a];if(typeof c==='string'){return c;}
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};$.toJSON=function(o,compact)
{var type=typeof(o);if(type=="undefined")
return"undefined";else if(type=="number"||type=="boolean")
return o+"";else if(o===null)
return"null";if(type=="string")
{return $.quoteString(o);}
if(type=="object"&&typeof o.toJSON=="function")
return o.toJSON(compact);if(type!="function"&&typeof(o.length)=="number")
{var ret=[];for(var i=0;i<o.length;i++){ret.push($.toJSON(o[i],compact));}
if(compact)
return"["+ret.join(",")+"]";else
return"["+ret.join(", ")+"]";}
if(type=="function"){throw new TypeError("Unable to convert object of type 'function' to json.");}
var ret=[];for(var k in o){var name;type=typeof(k);if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;var val=$.toJSON(o[k],compact);if(typeof(val)!="string"){continue;}
if(compact)
ret.push(name+":"+val);else
ret.push(name+": "+val);}
return"{"+ret.join(", ")+"}";};$.compactJSON=function(o)
{return $.toJSON(o,true);};$.evalJSON=function(src)
{return eval("("+src+")");};$.secureEvalJSON=function(src)
{var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};})(jQuery);
//}}}
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
! News
# This @news link will open the news space.<br><br>
# This News@news link only works, if you did include the space named: @following and if you view the [[wiki|http://pmario.tiddlyspace.com/#News]] representation of this tiddler. <br><br>
# If it doesn't make sense, you probably clicked the wrong one :)
have fun!
|''Name''|CodeMirrorPluginInfo|
|''Description''|Documentation for [[zCodeMirrorPlugin]]|
|''Author''|PMario|
|''Source''|https://github.com/pmario/tw.CodeMirrorPlugin|
|''Documentation''|http://codemirror.tiddlyspace.com/|
|''Feedback''|Feedback is very welcome at [[TWGroup]]|
|''License''|see: [[zCodeMirrorPlugin]]|
|''Keywords''|editor syntax highlighting color code|
!Documentation
!!!! ToolbarCommands
<<<
There are 2 new toolbar commands:
* {{{cmEdit}}} .. open tiddler for codemirror edit mode. Add this one to ToolbarCommands "~ViewToolbar" slice.
* {{{cmSave}}} .. open tiddler for codemirror edit mode. Add this one to ToolbarCommands "~EditToolbar" slice.
<<<
!!!! ViewTemplate
<<<
Add the following span to the ViewTemplate tiddler at "subtitle" definition.
<!--{{{-->
(type: <span macro='view content-type link'></span>)
<!--}}}-->
<<<
!!!! EditTemplate
<<<
To change the source type, add the following line to the EditTemplate, right below the "edit title" macro.
<!--{{{-->
<div class='toolbar' macro='typeChooser'></div>
<!--}}}-->
<<<
!!!! TiddlySpace Icons
<<<
If you use codemirror editor with TiddlySpace you'll need to create new icons
* Just create a new tiddler named [[cmEdit]] and copy the [[editTiddler]] content into "cmEdit".
* [[saveTiddler]] goes to [[cmSave]].
* There is an [[editTiddlerReadOnly]] icon, which is basically a "view icon". For codemirror, there is no need to change this one.
<<<
!!!! Global Settings
<<<
* <<option chkInsertTab>>chkInsertTab option cookie ''should be disabled'' to use CM key-handling. If {{{chkInsertTab}}} is active, keyhandling is hardcoded. {{{extraKeys}}} settings in CodeMirrorConfig are ignored.
* Learn more at ExtraKeysAddOn plugin.
<<<
!!!! StyleSheet
<<<
* The plugin automatically creates a shadow StyleSheetCodeMirror tiddler, that can be adjusted to your needs.
<<<
!!!! Macros
<<<
The plugin contains some additional macros, to get an overview, which modes are activated.
Modes: {{{<<cmModes>>}}} ... displays the usable modes seen below.
> Available Modes: <<cmModes>>
MIMEs: {{{<<cmMimes>>}}} ... displays the usable mime types seen below. Same order as modes.
> Available MIMEs: <<cmMimes>>
<<<
!!!! Text
<<<
{{{
{{{
This will produce a plain text block!
}}}
}}}
{{{
This is a plain text block!
}}}
<<<
!!!! CSS
<<<
{{{
/*{{{*/
.cssClass {
display: block; !important;
}
/*}}}*/
}}}
will render like:
/*{{{*/
.cssClass {
display: block; !important;
}
/*}}}*/
<<<
!!!! XML
<<<
{{{
<!--{{{-->
<html>
<div id='myId' class='dp50'>some text </div>
</html>
<!--}}}-->
}}}
will render like:
<!--{{{-->
<html>
<div id='myId' class='dp50'>some text </div>
</html>
<!--}}}-->
<<<
!!!! Plugin
<<<
{{{
//{{{
(function($) {
config.macros.highlightSyntax = {
var a = b = 0;
// your code here!
}
})(jQuery);
//}}}
}}}
will render like:
//{{{
(function($) {
config.macros.highlightSyntax = {
var a = b = 0;
// your code here!
}
})(jQuery);
//}}}
<<<
!!!! Code sample
<<<
<!--{{{-->
<code class="brush:javascript">
// comment
var a = b = 0;
a = 17;
</code>
<!--}}}-->
will render like
<code class="brush:javascript">
// comment
var a = b = 0;
a = 17;
</code>
<<<
!! Advanced Options
<<<
Guess syntax: <<option chkGuessSyntax>> .. If activated, ~TiddlyWiky <pre> blocks will be rendered according to there block braces, like described obove.
Expert mode: <<option chkExpertSyntax>> .. If activated, additional values below will be used
{{{ {{{ }}} txtShText: <<option txtShText>> eg: 'brush:text'
{{{ /*{{{*/ }}} txtShCss: <<option txtShCss>> eg: 'brush:css'
{{{ //{{{ }}} txtShPlugin: <<option txtShPlugin>> 'brush:js'
{{{ <!--{{{-->> }}} txtShXml: <<option txtShXml>> 'brush:xml'
If you want to change the default values eg for C++, add the following to a [[zzConfig]] tiddler and tag it "systemConfig"
//{{{
config.options.chkGuessSyntax = true;
config.options.chkExpertSyntax = true;
config.options.txtShPlugin = 'brush:clike';
//}}}
and use the following backets to cover your code
{{{
//{{{
cpp code comes here.
//}}}
}}}
All possible "brushes" can be found at: [[CodeMirror homepage|http://codemirror.net]]
<<<
!! You need a different mode?
* Go to [[CodeMirror compression API page| http://codemirror.net/compress.html]]
* Select your mode
* Create a minified version
* Copy paste it into a tiddler eg: clike.js
** Add the line {{{|''Requires''|codemirror.js|}}} at the top of the tiddler
*** see eg: [[css.js]]
** Tag the new tiddler ''systemConfig''
** Save and reload
* Have a look at Advanced options or use the {{{<code class="brush: ... >}}} tag described above.
!! List needed tiddlers tagged "cmtw" and "cmtwAddOn"
<<<
''If you want to roll your own version, the following tiddlers are needed.''
<<list filter [tag[cmtw]]>>
<<<
<<<
''There are usefull addOns too''
<<list filter [tag[cmtwAddOn]]>>
<<<
!!! highlightSyntax Macro
<<<
*The {{{highlightSyntax}}} macro is only needed if you have inline html blocks, like shown below.
<!--{{{-->
<html>
<pre class='brush:clike'>
// your code
</pre>
</html>
<<highlightSyntax>> .. will render the <pre> blocks shown above.
<!--}}}-->
<<<
!!!! Parameters
<<<
{{{<<highlightSyntax [tagName]>>}}}
*will render all blocks, with any defined tag name. eg: tagName = code.
*[tagName] is optional. Default is "pre".
<<<
!!! Revision History
<<<
* V 0.2.8 2012-06-23
** "smartTab" handling adjusted. see: ExtraKeysAddOn
** minor documentation adjustments about ViewTemplate, EditTemplate requirements.
* V 0.2.7 2012-03-13
** Editor refresh fixed, TypeChooser height fixed.
* V 0.2.6 2012-03-13
** Added functions to make editor height persistent.
* V 0.2.5 2012-02-07
** update codemirror library to v2.21 including all "support" libraries.
** TAB key handling improved. Extra keys handling moved to ExtraKeysAddOn
** F11 toggle editor height moved to ExtraKeysAddOn.
* V 0.2.4 2012-01-31
** slightly better TAB key handling. Internal testing only
* V 0.2.3 2012-01-11
** renames everything codemirror2 -> codemirror
** Toggle max height mode implemented hardcoded key: 'F11'
* V 0.2.1 2012-01-10
** Toggle max height mode implemented hardcoded key: 'F11'
* V 0.2.0 2011-10-23
** update to codeMirror lib v2.2
** indentation / tab handling fix
* V 0.1.7 2011-10-27
** little docu fix
* V 0.1.6 2011-10-05
** several bug fixes
** improved handling, initializing ...
* V 0.1.4 2011-09-25
** resize hack changed
* V 0.1.0 2011-09-07
** inital release
<<<
/*{{{*/
.tiddler .originButton div {
display: inline-block;
}
.tiddler .spaceSiteIcon .siteIcon {
_display: inline; /* IE doesn't like inline-block */
}
.tiddler .originButton {
display: block;
}
.selected .tagging,
.selected .tagging:hover {
border: none;
background: none;
}
.tagging {
float: none;
background: none;
border: none;
}
.tagging li.listTitle {
margin-left: 0px;
}
.t