Changes made: \n* Updated to 2.0.7
Updated to 2.0.8.
Added DisplayTiddlerGlyphsPlugin, minor updates to other plugins.
A placid starlet is self-actualized. The womanly alchemist barely plays pinochle with a botched clodhopper, and the alchemist defined by a guardian angel seeks a girl. Toscanini, the friend of Lila and Desdemona, goes to sleep with a shadow defined by a gonad. Some maestro defined by a tea party reads a magazine, and a ballerina daydreams; however, a tenor defined by a boy seeks a haunch. A self-actualized lunatic plans an escape from the curse a maestro. A haunch inside a starlet is unseemly. Most people believe that a tenor over an omphalos trades baseball cards with the ruffian, but they need to remember how overwhelmingly the uxorious girl feels nagging remorse. Sometimes a bubble bath sweeps the floor, but a toothpick related to a ribbon always operates a small fruit stand with the tea party! Indeed, a stalactite secretly admires a mastadon. A coward near a dissident seeks an onlooker. If a haunch mournes an amour-propre inside the dissident, then another widow rejoices. Toscanini and I took a cleavage inside a shadow (with a tea party behind a snow, the placid piroshki, a few gypsys, and a frightened gypsy) to arrive at a state of intimacy where we can hardly make a truce with our amour-propre. Mitzi, although somewhat soothed by a bubble bath over a toothache and a taxidermist near another labyrinth, still sanitizes her from a necromancer, conquer her the impresario with a womanly omphalos, and barely plays pinochle with the dark side of her lunatic.
Cleavage prefers a ribbon. The necromancer is wily. Mitzi, although somewhat soothed by the bodice ripper and an usually womanly gypsy, still slyly confesses her from the hand inside a stalactite, hardly be a big fan of her a wily ribbon with a cigar around the debutante, and carelessly throws a likeable bodice ripper at the dark side of her guardian angel. Unlike so many cream puffs who have made their rascally cleavage abhorrent to us, amour-propres remain inexorably friendly. The piroshki near a dissident is rapacious. The thoroughly chic mirror is completely ghastly. A comely lunatic laughs and drinks all night with the starlet. A guardian angel living with a mastadon avoids contact with the lowly cream puff. A girl hibernates, and an alchemist knowingly ignores a chic fetishist. The onlooker is sprightly.
Updated to 2.0.10
A menagé à trois over a guardian angel shares a shower with the dilettante near a cleavage. A midwife hardly avoids contact with the underhandedly nefarious clock. A taxidermist beyond a swamp flies into a rage, and an irreconcilable cleavage earns frequent flier miles; however, the somnambulist over a pocket pours freezing cold water on an onlooker. A self-actualized widow accurately shares a shower with the frightened debutante. He called her Nimbo (or was it Desdemona?). If a pocket from a haunch tries to seduce some dilettante, then a gonad near the midwife goes to sleep. Jean-Pierre and I took a frightened shadow (with the curse around a dahlia, a womanly lunatic, a few cleavages, and the botched labyrinth) to arrive at a state of intimacy where we can seldom brainwash our clock. If the necromancer buries a wobbly cigar, then a labyrinth around a bubble prays. Sometimes a swamp near a cup reads a magazine, but a rascally maestro always often teaches a mastadon! Mitzi and I took an amour-propre near a bicep (with another toothpick living with the bubble, the hand for a lunatic, a few dilettantes, and another boy) to arrive at a state of intimacy where we can barely secretly admire our ribbon. Sometimes another gypsy about an omphalos daydreams, but the sheepish maestro always boogies a cream puff beyond the debutante! The Interloper and I took an onlooker (with another ruffian, a bride beyond a curse, a few tenors, and a lunatic living with a trombone) to arrive at a state of intimacy where we can almost make love to our stalactite. Indeed, a dissident ostensibly sanitizes an omphalos over an alchemist. Scheherazade and I took a piroshki (with the wobbly toothache, the toothpick for the pocket, a few dahlias, and some trombone behind a trombone) to arrive at a state of intimacy where we can carelessly make love to our ballerina.
A philosopher from a maestro learns a hard lesson from an alchemist near the waif. A ghastly ruffian, a tea party inside an alchemist, and a starlet are what got Scheherazade into trouble. When a rhetorical hand reads a magazine, a debutante about the cleavage prays. The bicep dances with a fetishist beyond a dissident. A ribbon learns a hard lesson from an uxorious bicep. Now and then, a fetishist wisely satiates a waif. Now and then, some dissident usually throws a ribbon toward an omphalos at the toothache. Unlike so many bubble baths who have made their often darling toothpick abhorrent to us, dilettantes remain ungodly. When a bonbon leaves, some shadow about a trombone returns home. Now and then, a curmudgeonly boy hardly is a big fan of a shadow. A cleavage avoids contact with the accurately saintly pocket, but another lovely cigar ostensibly assimilates the mirror defined by the bubble bath. The girl about a waif dies, and a slovenly marzipan completely boogies a shadow for another onlooker. Jean-Pierre and I took some wily trombone (with the clock, a somewhat nefarious bubble, a few starlets, and a clock behind the onlooker) to arrive at a state of intimacy where we can ostensibly knowingly be a big fan of our clock.
This TiddlyWiki site is Creator-aware! Look at the Index tab on the right for some uses. The ''Timeline'' and ''All'' tabs are the same-ol-same-ol, but the [[Author|TabAuthor]] and [[Mine|TabMine]] tabs are new.\n* [[Author|TabAuthor]] lists all tiddles grouped by Creator (the original author). You may notice some entries by Bob, Joe, and Steve.\n* [[Mine|TabMine]] will list //only// the tiddles created or modified by //you//, the reader. Try changing your identity <<option txtUserName>> to one of these identities and flip back to [[Mine|TabMine]] (to make it refresh). It should list only the tiddles for that identity.\n\nHow to add a ''Creator'' property to your Tiddles:\n# Follow CreatorHack to modify your TiddleWiki code (based on 2.0.6)\n# Add whichever of the tiddles you want (ignore the TransitiveVampire content ;))\n\nFuture additions may include:\n* an admin mechanism to modify the creator\n* support in the ImportTiddlersPlugin (it works .. I mean add visibility .. options ... that sore of stuff)\n
In order to add ''creator'' to your tiddle metadata, you'll need to edit your source code to match what follows. Replace existing methods with the code below. Most (if not all) could be implemented as a plugin ... except maybe the root {{{Tiddler()}}} function?\n\n/*{{{*/\n// ---------------------------------------------------------------------------------\n// Tiddler() object\n// ---------------------------------------------------------------------------------\n\nfunction Tiddler()\n{\n this.title = null;\n this.text = null;\n this.modifier = null;\n this.modified = new Date();\n this.creator = null;\n this.created = new Date();\n this.links = [];\n this.tags = [];\n return this;\n}\n\n// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()\nTiddler.prototype.loadFromDiv = function(divRef,title)\n{\n var text = Tiddler.unescapeLineBreaks(divRef.firstChild ? divRef.firstChild.nodeValue : "");\n var modifier = divRef.getAttribute("modifier");\n var modified = Date.convertFromYYYYMMDDHHMM(divRef.getAttribute("modified"));\n var c = divRef.getAttribute("created");\n var created = c ? Date.convertFromYYYYMMDDHHMM(c) : modified;\n var ctor = divRef.getAttribute("creator");\n var creator = ctor ? ctor : modifier;\n var tags = divRef.getAttribute("tags");\n this.assign(title,text,modifier,modified,tags,created,creator);\n return this;\n}\n\n// Format the text for storage in an HTML DIV\nTiddler.prototype.saveToDiv = function()\n{\n return '<div tiddler="%0" modifier="%1" modified="%2" creator="%3" created="%4" tags="%5">%6</div>'.format([\n this.title.htmlEncode(),\n this.modifier.htmlEncode(),\n this.modified.convertToYYYYMMDDHHMM(),\n this.creator.htmlEncode(),\n this.created.convertToYYYYMMDDHHMM(),\n this.getTags().htmlEncode(),\n this.escapeLineBreaks().htmlEncode()\n ]);\n}\n\n/*}}}*/\n\n/*{{{*/\n// Change the text and other attributes of a tiddler\nTiddler.prototype.set = function(title,text,modifier,modified,tags,created,creator)\n{\n this.assign(title,text,modifier,modified,tags,created,creator);\n this.changed();\n return this;\n}\n\n// Change the text and other attributes of a tiddler without triggered a tiddler.changed() call\nTiddler.prototype.assign = function(title,text,modifier,modified,tags,created,creator)\n{\n var textChanged = false;\n\n if(title != undefined)\n this.title = title;\n if(text != undefined)\n {\n textChanged = (this.text != text);\n this.text = text;\n }\n if(modifier != undefined)\n {\n // Probably should have a config option for this behavior.....\n // Ignore modifier if text (body) did not change.\n // This means the modifier does not change if you only change tags (for example).\n // Makes it easier to find other people's plugins that you actually made changes to.\n // To restore original behavior, replace this chunk of code with just:\n // this.modifier = modifier;\n if (textChanged || this.modifier == null) \n {\n this.modifier = modifier;\n }\n }\n if(modified != undefined)\n this.modified = modified;\n if(created != undefined)\n this.created = created;\n if(creator != undefined)\n this.creator = creator;\n if(tags != undefined)\n this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags;\n else if(this.tags == undefined)\n this.tags = [];\n return this;\n}\n\n/*}}}*/\n\n/*{{{*/\n\nTiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags)\n{\n var tiddler = this.fetchTiddler(title);\n var created;\n var creator;\n if(tiddler)\n {\n created = tiddler.created; // preserve created date\n creator = tiddler.creator; // preserve creator\n this.deleteTiddler(title);\n }\n else\n {\n tiddler = new Tiddler();\n created = modified;\n creator = modifier;\n }\n tiddler.set(newTitle,newBody,modifier,modified,tags,created,creator);\n this.addTiddler(tiddler);\n if(title != newTitle)\n this.notify(title,true);\n this.notify(newTitle,true);\n this.setDirty(true);\n return tiddler;\n}\n\n/*}}}*/
/***\n|''Name:''|DataTiddlerPlugin|\n|''Version:''|1.0.4 (2006-02-05)|\n|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|\n|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|\n|''Licence:''|[[BSD open source license]]|\n|''TiddlyWiki:''|1.2.38+, 2.0|\n|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|\n!Description\nEnhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).\n\nSuch tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers. \n\n''//Example: "Table with all December Expenses"//''\n{{{\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\n}}}\n//(This assumes that expenses are stored in tiddlers tagged with "expense".)//\n<<forEachTiddler\n where\n 'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'\n write\n '"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\sn"'\n>>\nFor other examples see DataTiddlerExamples.\n\n\n\n\n''Access and Modify Tiddler Data''\n\nYou can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields. \n\nThese values can be accessed and modified through the following Tiddler methods:\n|!Method|!Example|!Description|\n|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n\nAlternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.\n|!Method|!Description|\n|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|\n|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|\n|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|\n|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|\n|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|\n//(For details on the various functions see the detailed comments in the source code.)//\n\n\n''Data Representation in a Tiddler''\n\nThe data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]]. \n\n//''Data Section Example:''//\n{{{\n<data>{"isVIP":true,"user":"John Brown","age":34}</data>\n}}}\n\nThe data section is not displayed when viewing the tiddler (see also "The showData Macro").\n\nBeside the data section a tiddler may have all kind of other content.\n\nTypically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.\n\n\n''Saving Changes''\n\nThe "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.\n\n\n''Notifications''\n\nNo notifications are sent when a tiddler's data value is changed through the "setData" methods. \n\n''Escape Data Section''\nIn case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.\n\n\n''The showData Macro''\n\nBy default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:\n\n''Syntax:'' \n|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|\n|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|\n|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|\n|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|\n\n\n!Revision history\n* v1.0.4 (2006-02-05)\n** Bugfix: showData fails in TiddlyWiki 2.0\n* v1.0.3 (2006-01-06)\n** Support TiddlyWiki 2.0\n* v1.0.2 (2005-12-22)\n** Enhancements:\n*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.\n*** Improved (JSON) error messages.\n** Bugs fixed: \n*** References are not updated when using the DataTiddler.\n*** Changes to compound objects are not always saved.\n*** "~</data>" is not rendered correctly (expected "</data>")\n* v1.0.1 (2005-12-13)\n** Features: \n*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed\n** Bugs fixed: \n*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)\n* v1.0.0 (2005-12-12)\n** initial version\n\n!Code\n***/\n//{{{\n//============================================================================\n//============================================================================\n// DataTiddlerPlugin\n//============================================================================\n//============================================================================\n\n// Ensure that the DataTiddler Plugin is only installed once.\n//\nif (!version.extensions.DataTiddlerPlugin) {\n\n\n\nversion.extensions.DataTiddlerPlugin = {\n major: 1, minor: 0, revision: 4,\n date: new Date(2006, 2, 5), \n type: 'plugin',\n source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"\n};\n\n// For backward compatibility with v1.2.x\n//\nif (!window.story) window.story=window; \nif (!TiddlyWiki.prototype.getTiddler) TiddlyWiki.prototype.getTiddler = function(title) { return t = this.tiddlers[title]; return (t != undefined && t instanceof Tiddler) ? t : null; } \n\n//============================================================================\n// DataTiddler Class\n//============================================================================\n\n// ---------------------------------------------------------------------------\n// Configurations and constants \n// ---------------------------------------------------------------------------\n\nfunction DataTiddler() {\n}\n\nDataTiddler = {\n // Function to stringify a JavaScript value, producing the text for the data section content.\n // (Must match the implementation of DataTiddler.parse.)\n //\n stringify : null,\n \n\n // Function to parse the text for the data section content, producing a JavaScript value.\n // (Must match the implementation of DataTiddler.stringify.)\n //\n parse : null\n};\n\n// Ensure access for IE\nwindow.DataTiddler = DataTiddler;\n\n// ---------------------------------------------------------------------------\n// Data Accessor and Mutator\n// ---------------------------------------------------------------------------\n\n\n// Returns the value of the given data field of the tiddler.\n// When no such field is defined or its value is undefined\n// the defaultValue is returned.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.getData = function(tiddler, field, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataValue(t, field, defaultValue);\n}\n\n\n// Sets the value of the given data field of the tiddler to\n// the value. When the value is equal to the defaultValue\n// no value is set (and the field is removed)\n//\n// Changing data of a tiddler will not trigger notifications.\n// \n// @param tiddler either a tiddler name or a tiddler\n//\nDataTiddler.setData = function(tiddler, field, value, defaultValue) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler+ "("+t+")";\n }\n\n DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);\n}\n\n\n// Returns the data object of the tiddler, with a property for every field.\n//\n// The properties of the returned data object may only be read and\n// not be modified. To modify the data use DataTiddler.setData(...) \n// or the corresponding Tiddler method.\n//\n// If no data section is defined a new (empty) object is returned.\n//\n// @param tiddler either a tiddler name or a Tiddler\n//\nDataTiddler.getDataObject = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.getTiddlerDataObject(t);\n}\n\n// Returns the text of the content of the data section of the tiddler.\n//\n// When no data section is defined for the tiddler null is returned \n//\n// @param tiddler either a tiddler name or a Tiddler\n// @return [may be null]\n//\nDataTiddler.getDataText = function(tiddler) {\n var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;\n if (!(t instanceof Tiddler)) {\n throw "Tiddler expected. Got "+tiddler;\n }\n\n return DataTiddler.readDataSectionText(t);\n}\n\n\n// ---------------------------------------------------------------------------\n// Internal helper methods (must not be used by code from outside this plugin)\n// ---------------------------------------------------------------------------\n\n// Internal.\n//\n// The original JSONError is not very user friendly, \n// especially it does not define a toString() method\n// Therefore we extend it here.\n//\nDataTiddler.extendJSONError = function(ex) {\n if (ex.name == 'JSONError') {\n ex.toString = function() {\n return ex.name + ": "+ex.message+" ("+ex.text+")";\n }\n }\n return ex;\n}\n\n// Internal.\n//\n// @param t a Tiddler\n//\nDataTiddler.getTiddlerDataObject = function(t) {\n if (t.dataObject == undefined) {\n var data = DataTiddler.readData(t);\n t.dataObject = (data) ? data : {};\n }\n \n return t.dataObject;\n}\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {\n var value = DataTiddler.getTiddlerDataObject(tiddler)[field];\n return (value == undefined) ? defaultValue : value;\n}\n\n\n// Internal.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n var oldValue = data[field];\n \n if (value == defaultValue) {\n if (oldValue != undefined) {\n delete data[field];\n DataTiddler.save(tiddler);\n }\n return;\n }\n data[field] = value;\n DataTiddler.save(tiddler);\n}\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns its text\n// (as a String).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readDataSectionText = function(tiddler) {\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n if (matches == null || !matches[2]) {\n return null;\n }\n return matches[2];\n}\n\n// Internal.\n//\n// Reads the data section from the tiddler's content and returns it\n// (as an internalized object).\n//\n// Returns null when no data is defined.\n//\n// @param tiddler a Tiddler\n// @return [may be null]\n//\nDataTiddler.readData = function(tiddler) {\n var text = DataTiddler.readDataSectionText(tiddler);\n try {\n return text ? DataTiddler.parse(text) : null;\n } catch(ex) {\n throw DataTiddler.extendJSONError(ex);\n }\n}\n\n// Internal.\n// \n// Returns the serialized text of the data of the given tiddler, as it\n// should be stored in the data section.\n//\n// @param tiddler a Tiddler\n//\nDataTiddler.getDataTextOfTiddler = function(tiddler) {\n var data = DataTiddler.getTiddlerDataObject(tiddler);\n return DataTiddler.stringify(data);\n}\n\n\n// Internal.\n// \nDataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {\n var index = s.indexOf(subString, startIndex);\n while ((index > 0) && (s[index-1] == '~')) { \n index = s.indexOf(subString, index+1);\n }\n return index;\n}\n\n// Internal.\n//\nDataTiddler.getDataSectionInfo = function(text) {\n // Special care must be taken to handle "<data>" and "</data>" texts inside\n // a data section. \n // Also take care not to use an escaped <data> (i.e. "~<data>") as the start \n // of a data section. (Same for </data>)\n\n // NOTE: we are explicitly searching for a data section that contains a JSON\n // string, i.e. framed with braces. This way we are little bit more robust in\n // case the tiddler contains unescaped texts "<data>" or "</data>". This must\n // be changed when using a different stringifier.\n\n var startTagText = "<data>{";\n var endTagText = "}</data>";\n\n var startPos = 0;\n\n // Find the first not escaped "<data>".\n var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);\n if (startDataTagIndex < 0) {\n return null;\n }\n\n // Find the *last* not escaped "</data>".\n var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);\n if (endDataTagIndex < 0) {\n return null;\n }\n var nextEndDataTagIndex;\n while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {\n endDataTagIndex = nextEndDataTagIndex;\n };\n\n return {\n prefixEnd: startDataTagIndex, \n dataStart: startDataTagIndex+(startTagText.length)-1, \n dataEnd: endDataTagIndex, \n suffixStart: endDataTagIndex+(endTagText.length)\n };\n}\n\n// Internal.\n// \n// Returns the "matches" of a content of a DataTiddler on the\n// "data" regular expression. Return null when no data is defined\n// in the tiddler content.\n//\n// Group 1: text before data section (prefix)\n// Group 2: content of data section\n// Group 3: text behind data section (suffix)\n//\n// @param tiddler a Tiddler\n// @return [may be null] null when the tiddler contains no data section, otherwise see above.\n//\nDataTiddler.getDataTiddlerMatches = function(tiddler) {\n var text = tiddler.text;\n var info = DataTiddler.getDataSectionInfo(text);\n if (!info) {\n return null;\n }\n\n var prefix = text.substr(0,info.prefixEnd);\n var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);\n var suffix = text.substr(info.suffixStart);\n \n return [text, prefix, data, suffix];\n}\n\n\n// Internal.\n//\n// Saves the data in a <data> block of the given tiddler (as a minor change). \n//\n// The "chkAutoSave" and "chkForceMinorUpdate" options are respected. \n// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.\n//\n// Notifications are not send. \n//\n// This method should only be called when the data really has changed. \n//\n// @param tiddler\n// the tiddler to be saved.\n//\nDataTiddler.save = function(tiddler) {\n\n var matches = DataTiddler.getDataTiddlerMatches(tiddler);\n\n var prefix;\n var suffix;\n if (matches == null) {\n prefix = tiddler.text;\n suffix = "";\n } else {\n prefix = matches[1];\n suffix = matches[3];\n }\n\n var dataText = DataTiddler.getDataTextOfTiddler(tiddler);\n var newText = \n (dataText != null) \n ? prefix + "<data>" + dataText + "</data>" + suffix\n : prefix + suffix;\n if (newText != tiddler.text) {\n // make the change in the tiddlers text\n \n // ... see DataTiddler.MyTiddlerChangedFunction\n tiddler.isDataTiddlerChange = true;\n \n // ... do the action change\n tiddler.set(\n tiddler.title,\n newText,\n config.options.txtUserName, \n config.options.chkForceMinorUpdate? undefined : new Date(),\n tiddler.tags);\n\n // ... see DataTiddler.MyTiddlerChangedFunction\n delete tiddler.isDataTiddlerChange;\n\n // Mark the store as dirty.\n store.dirty = true;\n \n // AutoSave if option is selected\n if(config.options.chkAutoSave) {\n saveChanges();\n }\n }\n}\n\n// Internal.\n//\nDataTiddler.MyTiddlerChangedFunction = function() {\n // Remove the data object from the tiddler when the tiddler is changed\n // by code other than DataTiddler code. \n //\n // This is necessary since the data object is just a "cached version" \n // of the data defined in the data section of the tiddler and the \n // "external" change may have changed the content of the data section.\n // Thus we are not sure if the data object reflects the data section \n // contents. \n // \n // By deleting the data object we ensure that the data object is \n // reconstructed the next time it is needed, with the data defined by\n // the data section in the tiddler's text.\n \n // To indicate that a change is a "DataTiddler change" a temporary\n // property "isDataTiddlerChange" is added to the tiddler.\n if (this.dataObject && !this.isDataTiddlerChange) {\n delete this.dataObject;\n }\n \n // call the original code.\n DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);\n}\n\n\n//============================================================================\n// Formatters\n//============================================================================\n\n// This formatter ensures that "~<data>" is rendered as "<data>". This is used to \n// escape the "<data>" of a data section, just in case someone really wants to use\n// "<data>" as a text in a tiddler and not start a data section.\n//\n// Same for </data>.\n//\nconfig.formatters.push( {\n name: "data-escape",\n match: "~<\s\s/?data>",\n\n handler: function(w) {\n w.outputText(w.output,w.matchStart + 1,w.nextMatch);\n }\n} )\n\n\n// This formatter ensures that <data>...</data> sections are not rendered.\n//\nconfig.formatters.push( {\n name: "data",\n match: "<data>",\n\n handler: function(w) {\n var info = DataTiddler.getDataSectionInfo(w.source);\n if (info && info.prefixEnd == w.matchStart) {\n w.nextMatch = info.suffixStart;\n } else {\n w.outputText(w.output,w.matchStart,w.nextMatch);\n }\n }\n} )\n\n\n//============================================================================\n// Tiddler Class Extension\n//============================================================================\n\n// "Hijack" the changed method ---------------------------------------------------\n\nDataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;\nTiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;\n\n// Define accessor methods -------------------------------------------------------\n\n// Returns the value of the given data field of the tiddler. When no such field \n// is defined or its value is undefined the defaultValue is returned.\n//\n// When field is undefined (or null) the data object is returned. (See \n// DataTiddler.getDataObject.)\n//\n// @param field [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n// @return [may be null, undefined]\n//\nTiddler.prototype.data = function(field, defaultValue) {\n return (field) \n ? DataTiddler.getTiddlerDataValue(this, field, defaultValue)\n : DataTiddler.getTiddlerDataObject(this);\n}\n\n// Sets the value of the given data field of the tiddler to the value. When the \n// value is equal to the defaultValue no value is set (and the field is removed).\n//\n// @param value [may be null, undefined]\n// @param defaultValue [may be null, undefined]\n//\nTiddler.prototype.setData = function(field, value, defaultValue) {\n DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);\n}\n\n\n//============================================================================\n// showData Macro\n//============================================================================\n\nconfig.macros.showData = {\n // Standard Properties\n label: "showData",\n prompt: "Display the values stored in the data section of the tiddler"\n}\n\nconfig.macros.showData.handler = function(place,macroName,params) {\n // --- Parsing ------------------------------------------\n\n var i = 0; // index running over the params\n // Parse the optional "JSON"\n var showInJSONFormat = false;\n if ((i < params.length) && params[i] == "JSON") {\n i++;\n showInJSONFormat = true;\n }\n \n var tiddlerName = story.findContainingTiddler(place).id.substr(7);\n if (i < params.length) {\n tiddlerName = params[i]\n i++;\n }\n\n // --- Processing ------------------------------------------\n try {\n if (showInJSONFormat) {\n this.renderDataInJSONFormat(place, tiddlerName);\n } else {\n this.renderDataAsTable(place, tiddlerName);\n }\n } catch (e) {\n this.createErrorElement(place, e);\n }\n}\n\nconfig.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {\n var text = DataTiddler.getDataText(tiddlerName);\n if (text) {\n createTiddlyElement(place,"pre",null,null,text);\n }\n}\n\nconfig.macros.showData.renderDataAsTable = function(place,tiddlerName) {\n var text = "|!Name|!Value|\sn";\n var data = DataTiddler.getDataObject(tiddlerName);\n if (data) {\n for (var i in data) {\n var value = data[i];\n text += "|"+i+"|"+DataTiddler.stringify(value)+"|\sn";\n }\n }\n \n wikify(text, place);\n}\n\n\n// Internal.\n//\n// Creates an element that holds an error message\n// \nconfig.macros.showData.createErrorElement = function(place, exception) {\n var message = (exception.description) ? exception.description : exception.toString();\n return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);\n}\n\n// ---------------------------------------------------------------------------\n// Stylesheet Extensions (may be overridden by local StyleSheet)\n// ---------------------------------------------------------------------------\n//\nsetStylesheet(\n ".showDataError{color: #ffffff;background-color: #880000;}",\n "showData");\n\n\n} // of "install only once"\n//}}}\n\n\n\n/***\n!JSON Code, used to serialize the data\n//(embedded in the plugin tiddler to make it selfcontained)//\n***/\n//{{{\n/*\nCopyright (c) 2005 JSON.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe Software shall be used for Good, not Evil.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n/*\n The global object JSON contains two methods.\n\n JSON.stringify(value) takes a JavaScript value and produces a JSON text.\n The value must not be cyclical.\n\n JSON.parse(text) takes a JSON text and produces a JavaScript value. It will\n throw a 'JSONError' exception if there is an error.\n*/\nvar JSON = {\n copyright: '(c)2005 JSON.org',\n license: 'http://www.crockford.com/JSON/license.html',\n/*\n Stringify a JavaScript value, producing a JSON text.\n*/\n stringify: function (v) {\n var a = [];\n\n/*\n Emit a string.\n*/\n function e(s) {\n a[a.length] = s;\n }\n\n/*\n Convert a value.\n*/\n function g(x) {\n var c, i, l, v;\n\n switch (typeof x) {\n case 'object':\n if (x) {\n if (x instanceof Array) {\n e('[');\n l = a.length;\n for (i = 0; i < x.length; i += 1) {\n v = x[i];\n if (typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(v);\n }\n }\n e(']');\n return;\n } else if (typeof x.toString != 'undefined') {\n e('{');\n l = a.length;\n for (i in x) {\n v = x[i];\n if (x.hasOwnProperty(i) &&\n typeof v != 'undefined' &&\n typeof v != 'function') {\n if (l < a.length) {\n e(',');\n }\n g(i);\n e(':');\n g(v);\n }\n }\n return e('}');\n }\n }\n e('null');\n return;\n case 'number':\n e(isFinite(x) ? +x : 'null');\n return;\n case 'string':\n l = x.length;\n e('"');\n for (i = 0; i < l; i += 1) {\n c = x.charAt(i);\n if (c >= ' ') {\n if (c == '\s\s' || c == '"') {\n e('\s\s');\n }\n e(c);\n } else {\n switch (c) {\n case '\sb':\n e('\s\sb');\n break;\n case '\sf':\n e('\s\sf');\n break;\n case '\sn':\n e('\s\sn');\n break;\n case '\sr':\n e('\s\sr');\n break;\n case '\st':\n e('\s\st');\n break;\n default:\n c = c.charCodeAt();\n e('\s\su00' + Math.floor(c / 16).toString(16) +\n (c % 16).toString(16));\n }\n }\n }\n e('"');\n return;\n case 'boolean':\n e(String(x));\n return;\n default:\n e('null');\n return;\n }\n }\n g(v);\n return a.join('');\n },\n/*\n Parse a JSON text, producing a JavaScript value.\n*/\n parse: function (text) {\n var p = /^\ss*(([,:{}\s[\s]])|"(\s\s.|[^\sx00-\sx1f"\s\s])*"|-?\sd+(\s.\sd*)?([eE][+-]?\sd+)?|true|false|null)\ss*/,\n token,\n operator;\n\n function error(m, t) {\n throw {\n name: 'JSONError',\n message: m,\n text: t || operator || token\n };\n }\n\n function next(b) {\n if (b && b != operator) {\n error("Expected '" + b + "'");\n }\n if (text) {\n var t = p.exec(text);\n if (t) {\n if (t[2]) {\n token = null;\n operator = t[2];\n } else {\n operator = null;\n try {\n token = eval(t[1]);\n } catch (e) {\n error("Bad token", t[1]);\n }\n }\n text = text.substring(t[0].length);\n } else {\n error("Unrecognized token", text);\n }\n } else {\n token = operator = undefined;\n }\n }\n\n\n function val() {\n var k, o;\n switch (operator) {\n case '{':\n next('{');\n o = {};\n if (operator != '}') {\n for (;;) {\n if (operator || typeof token != 'string') {\n error("Missing key");\n }\n k = token;\n next();\n next(':');\n o[k] = val();\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next('}');\n return o;\n case '[':\n next('[');\n o = [];\n if (operator != ']') {\n for (;;) {\n o.push(val());\n if (operator != ',') {\n break;\n }\n next(',');\n }\n }\n next(']');\n return o;\n default:\n if (operator !== null) {\n error("Missing value");\n }\n k = token;\n next();\n return k;\n }\n }\n next();\n return val();\n }\n};\n//}}}\n/***\n!Setup the data serialization\n***/\n//{{{\nDataTiddler.format = "JSON";\nDataTiddler.stringify = JSON.stringify;\nDataTiddler.parse = JSON.parse;\n\n//}}}\n\n
Creator
// List tags you want "glyphed" in the form: //\n//// {{{tag:'}}}@@tagname@@{{{',wiki:'}}}@@anywikitext@@{{{'}}}\n// wiki text doesn't have to be a character, it can be an image, multiple chars, etc. //\n// ''NOTE:'' @@FireFox must be [[hacked|FireFoxSymbolFonts]] to display symbolic fonts (like Symbol or Webdings).@@//\n\ntag:'Broken',wiki:'@@color(red):font-family(Wingdings,Zapf Dingbats):û@@'\ntag:'Flagged',wiki:'@@color(green):font-family(Wingdings,Zapf Dingbats):O@@'\ntag:'Tools',wiki:'@@color(brown):font-family(Webdings):@@@' \ntag:'systemConfig',wiki:'@@color(cc9900):¤@@' \ntag:'Plugins',wiki:'@@color(grey):¤@@' // same as sysConfig, only grey.//\ntag:'Layout',wiki:'@@color(grey):font-family(Webdings):2@@'\ntag:'CSS',wiki:'@@color(purple):font-family(Webdings):>@@'\ntag:'Authors',wiki:'@@color(CC6600):font-size(125%):☺@@'\ntag:'Examples',wiki:'@@color(grey):font-family(Webdings):@@'\ntag:'Documentation',wiki:'@@color(blue):font-family(Webdings):i@@'\ntag:'References',wiki:'@@color(blue):font-family(Webdings):i@@'\ntag:'Tasks',wiki:'⇒'\ntag:'Journal',wiki:'@@color(CC6600):font-family(Wingdings,Zapf Dingbats):º@@'\ntag:'TransitiveVampire',wiki:'@@color(grey):font-family(Webdings):…@@'\ntag:'Done',wiki:'@@color(grey):font-family(Wingdings,Zapf Dingbats):ü@@'\n
/***\n|!Name:| ''@@font-size(large):font-variant(small-caps):~DisplayTiddlerGlyphsPlugin@@'' |\n|!Version:|1.0.0|\n|!Location|http://gwsyzygy.googlepages.com/creator.html#DisplayTiddlerGlyphsPlugin|\n|!Author:|GregWalker |\n|!Type:|Macro |\n|!Requires|~TW2.x|\n\n!Description\n<<<\nA macro for displaying //glyphs// according to the tags on a particular tiddler. Glyphs are defined in DisplayTiddlerGlyphData and don't have to be just a glyph (graphic character). They can be any wiki content, including images, text, buttons, popups, etc.\nAlso note the glyphs will display in the order they appear in DisplayTiddlerGlyphData, not the order of the tags on the tiddler. This is useful when displaying only the first glyph (like in ListAuthorPlugin).\n@@FireFox Users@@ Most of the glyphs on this site come from symbolic fonts. See FireFoxSymbolFonts to enable symbolic fonts on FF.\n// ''See also:''// ListAuthorPlugin //and// StyleSheet\n<<<\n\n!Examples\n|!Source|!Output|!Comments|h\n|{{{<<glyph systemConfig>>}}}|<<glyph systemConfig>>|//Shows glyph with specified name//|\n|{{{<<displayTiddlerGlyphs>>}}}|<<displayTiddlerGlyphs>>|//Shows all glyphs for current tiddler//|\n|{{{<<displayTiddlerGlyphs EchoMacro>> EchoMacro}}}|<<displayTiddlerGlyphs EchoMacro>> EchoMacro|//Shows all glyphs for specified tiddler//|\n|{{{<<displayTiddlerGlyphs ListAuthorPlugin 1>> ListAuthorPlugin}}}|<<displayTiddlerGlyphs ListAuthorPlugin 1>> ListAuthorPlugin|//Shows first matching glyph for specified tiddler. Note that "first" means first by order defined in in DisplayTiddlerGlyphData. The order of the //|\n\n!Additional Functions\n<<<\n* {{{config.macros.displayTiddlerGlyphs.createGlyphsElement(place, tiddler, //count//}}} - returns a DOM element (span) containing a tiddler's glyph(s).\n* {{{config.macros.displayTiddlerGlyphs.cache.fetchGlyph(name)}}} - returns a ''Glyph'' object for the specified tag name.\n<<<\n\n!History\n* 13-Jun-06, version 1.0.0, initial version\n\n!Future Enhancements\n* Config switch to allow for glyphs with all tiddler links\n** Control visibility via style sheets (i.e. 1st glyph class is g1, next g2, g3, ...)\n\n!Code\n***/\n\n/*{{{*/\nversion.extensions.DisplayTiddlerGlyphsPlugin = {major: 1, minor: 0, revision: 0, \n date: new Date(2006,6,13),\n source: "http://gwsyzygy.googlepages.com/creator.html#DisplayTiddlerGlyphsPlugin"\n};\nconfig.macros.displayTiddlerGlyphs = {};\nconfig.macros.displayTiddlerGlyphs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n var target=(params[0] ? store.getTiddler(params[0]) : tiddler);\n var count=(params[1] ? params[1] : -1);\n config.macros.displayTiddlerGlyphs.createGlyphsElement(place, target, count);\n}\nconfig.macros.glyph = {};\nconfig.macros.glyph.handler = function(place,macroName,params,wikifier,paramString,tiddler) {\n var glyph = config.macros.displayTiddlerGlyphs.cache.fetchGlyph(params[0]);\n if (glyph)\n glyph.display(place,tiddler);\n}\nconfig.macros.displayTiddlerGlyphs.createGlyphsElement = function(place,tiddler,count) {\n var wrapper = createTiddlyElement(place,"span",null,"glyphsWrapper");\n if (!tiddler || tiddler.tags.length==0) return wrapper;\n\n var glyphs = config.macros.displayTiddlerGlyphs.cache.match(tiddler.tags);\n if (count == undefined || count < 0 || count > glyphs.length) count = glyphs.length;\n for (var i=0;i<count;i++)\n glyphs[i].display(wrapper,tiddler);\n\n return wrapper;\n}\n\n// Construct a cache object to manage the glyph data.\nfunction GlyphCache()\n{\n var glyphs = {}; \n var valid = false;\n this.count = 0;\n this.invalidate = function() { valid = false; }\n this.addGlyph = function(glyph) {\n if (glyph.name) {glyphs[glyph.name] = glyph; this.count++;}\n };\n this.fetchGlyph = function(name) {\n if (!valid) this.load();\n return glyphs[name];\n };\n this.match = function(items) {\n if (!valid) this.load();\n var results = [];\n for(var i=0; i<items.length; i++)\n if (glyphs[items[i]]!=undefined)\n results.push(glyphs[items[i]]);\n results.sort(function (a,b) {if(a.index == b.index) return(0); else return (a.index < b.index) ? -1 : +1; });\n return results;\n };\n this.load = function() {\n this.glyphs = {}; \n this.count=0;\n var source=store.getTiddler("DisplayTiddlerGlyphData");\n if (source && source.text) \n {\n this.modified = source.modified;\n var entries=source.text.split("\sn");\n for (var i=0;i<entries.length;i++)\n this.addGlyph(new Glyph(entries[i], i));\n } \n valid = true;\n };\n\n // Register for notification if the glyph data tiddler changes.\n store.addNotification("DisplayTiddlerGlyphData", this.invalidate);\n return this;\n}\n\nfunction Glyph(data, index)\n{\n this.index = index;\n this.data = eval("x={" + data + "\sn};");\n this.name = this.data.tag;\n this.wiki = this.data.wiki;\n this.wikified = null;\n return this;\n}\n\nGlyph.prototype.display = function(place,tiddler) \n{\n var span = createTiddlyElement(place,"span",null,"glyphElement");\n span.setAttribute("title", this.name);\n if (this.wikified)\n span.innerHTML = this.wikified;\n else\n {\n wikify(this.wiki, span, null, null);\n if (span.innerHTML) this.wikified = span.innerHTML;\n }\n}\n\nconfig.macros.displayTiddlerGlyphs.cache = new GlyphCache();\n\n/*}}}*/\n\n/***\nThis plugin is released under the [[Creative Commons Attribution 2.5 License|http://creativecommons.org/licenses/by/2.5/]]\n***/\n
/***\n|!Name:| ''@@font-size(large):font-variant(small-caps):~EchoMacro@@'' |\n|!Version:|1.0.0|\n|!Location|http://gwsyzygy.googlepages.com/creator.html#EchoMacro|\n|!Author:|GregWalker |\n|!Type:|Macro Debugging Tool |\n|!Requires|~TW2.x|\n\n!Description\n<<<\n''echo'' will echo back all params passed to it, including each parameter's #, type, value, and //literal// value (unwikified). Useful for debugging exactly what is getting passed to a macro.\n<<<\n\n!Examples\n|!Source|!Output|h\n|{{{<<echo "Hello, World">>}}}|<<echo "Hello, World">>|\n|{{{<<echo this and "that" and [[the other]]>>}}}|<<echo this and "that" and [[the other]]>>|\n\n!History\n* 23-Mar-06, version 1.0.0, initial version\n\n!~ToDo\n* Update to new //enhanced// parameters in 2.0.7\n\n!Code\n***/\n/*{{{*/\nversion.extensions.EchoMacro = { major: 1, minor: 0, revision: 0, date: new Date(2006,3,23),\n source: "http://gwsyzygy.googlepages.com/creator.html#EchoMacro"\n};\n\nconfig.macros.echo = {};\nconfig.macros.echo.handler = function (place,macroName,params,wikifier,paramString,tiddler) {\n if (params.length == 0)\n wikify("//no params//",place);\n for(var i=0; i<params.length; i++)\n {\n wikify("params[" + i + "] (" + typeof(params[i]) + ") = '" + params[i] + "' {{{[" + (params[i] ? params[i].toString() : "null" ) + "]}}}\sn", place);\n } \n}\n\n/*}}}*/\n/***\nThis plugin is released under the [[Creative Commons Attribution 2.5 License|http://creativecommons.org/licenses/by/2.5/]]\n***/\n
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>\n<div class="title" macro="view title"></div>\n<table style="border:0px; width:100%;">\n<tr>\n<td><div class="editLabel">Title</div></td><td><div style="padding-right:1em;" class="editor" macro="edit title"></div></td>\n</tr><tr>\n<td><div class="editLabel">Creator</div></td><td><div style="padding-right:1em;" class="editor" macro="edit creator"></div></td>\n</tr><tr>\n<td><div class="editLabel">Tags</div></td><td><div style="padding-right:1em;" class="editor" macro="edit tags"></div></td>\n<tr></tr>\n<td> </td><td><div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div></td>\n</tr></table>\n<div class="editor" macro="edit text"></div>
To display symbolic fonts in FireFox (on Windows):\n# Open the font encoding file (Program Files/Mozilla FireFox/res/fonts/fontEncoding.properties)\n# Find the section labeled ''Symbol font''\n# Add the following entries to that section:\n{{{\nencoding.free3of9.ttf = windows-1252\nencoding.symbol.ttf = windows-1252\nencoding.wingdings.ttf = windows-1252\nencoding.wingdings2.ttf = windows-1252\nencoding.wingdings3.ttf = windows-1252\nencoding.webdings.ttf = windows-1252\n}}}\n\n@@NOTE:@@ FireFox upgrades tend to overwrite these changes, so you may need to reapply after a FF patch.\n\nFrom [[dmcritchie|http://www.mvps.org/dmcritchie/firefox/firefox.htm#wingdings]]. X users see http://hutchinson.belmont.ma.us/tth/manual/sec12.html#tth_sEc12.3
Creator of gkwWiki: http://gwsyzygy.googlepages.com/creator.html\n\n<<listByAuthor creator GregWalker>>\n
/***\n|!Name:| ''@@font-size(large):font-variant(small-caps):~ListAuthorPlugin@@'' |\n|!Version:|1.0.1|\n|!Location|http://gwsyzygy.googlepages.com/creator.html#ListAuthorPlugin|\n|!Author:|GregWalker |\n|!Type:|Macro Extension |\n|!Requires|~TW2.x|\n\n!Description\n<<<\nIt's a macro for listing by creator or modifier.\n<<<\n\n!Examples\n|!Source|!Output|h\n|{{{<<listByAuthor>>}}}|//lists all tiddlers grouped by creator//|\n|{{{<<listByAuthor modifier>>}}}|//lists all tiddlers grouped by modifier//|\n|{{{<<listByAuthor creator SomeUser>>}}}|//lists all tiddlers created by ''SomeUser''//|\n|{{{<<listByAuthor creator currentUser>>}}}|//lists all tiddlers created by the current user//|\n\n!History\n* 13-Jun-06, version 1.0.1, Added support for DisplayTiddlerGlyphsPlugin\n* 21-Mar-06, version 1.0.0, initial version\n\n!Code\n***/\n/*{{{*/\nversion.extensions.ListAuthorPlugin = { major: 1, minor: 0, revision: 1, \n date: new Date(2006,6,13),\n source: "http://gwsyzygy.googlepages.com/creator.html#ListAuthorPlugin"\n};\n\nconfig.macros.listByAuthor = {};\nconfig.macros.listByAuthor.handler = function(place,macroName,params)\n{\n var field = params[0] ? params[0] : "creator";\n var filter = params[1]=="currentUser" ? config.options.txtUserName : params[1];\n\n // sort by title first, then by author to end up with author then title.\n var tiddlers = store.reverseLookup("tags","excludeLists",false,"title");\n tiddlers.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });\n\n var lastAuthor = "";\n for(var t=0; t<tiddlers.length; t++)\n {\n var tiddler = tiddlers[t];\n var theAuthor = tiddler[field];\n if(filter==null || theAuthor==filter)\n {\n if(theAuthor != lastAuthor)\n {\n var theAuthorList = document.createElement("ul");\n place.appendChild(theAuthorList);\n if(filter==null)\n createTiddlyElement(theAuthorList,"li",null,"listTitle",tiddler[field]);\n lastAuthor = theAuthor;\n }\n var theAuthorListItem = createTiddlyElement(theAuthorList,"li",null,"listLink",null);\n if (config.macros.displayTiddlerGlyphs)\n {\n config.macros.displayTiddlerGlyphs.createGlyphsElement(theAuthorListItem,tiddler,1);\n }\n theAuthorListItem.appendChild(createTiddlyLink(place,tiddler.title,true));\n }\n }\n}\n\n/*}}}*/\n/***\nThis plugin is released under the [[Creative Commons Attribution 2.5 License|http://creativecommons.org/licenses/by/2.5/]]\n***/\n
!Plugins\n<<displayTiddlerGlyphs Creator 1>> [[Creator]]\n<<displayTiddlerGlyphs ListAuthorPlugin 1>> ListAuthorPlugin\n<<displayTiddlerGlyphs ScrollingTabsPlugin 1>> ScrollingTabsPlugin\n<<displayTiddlerGlyphs DisplayTiddlerGlyphsPlugin 1>> [[DisplayTiddler|DisplayTiddlerGlyphsPlugin]]- [[GlyphsPlugin|DisplayTiddlerGlyphsPlugin]]\n\n!Tools\n<<displayTiddlerGlyphs EchoMacro 1>> EchoMacro\n<<displayTiddlerGlyphs TestEval 1>> TestEval\n\n@@font-size(75%):TW v.<<version>>@@
<script type="text/javascript" language="javascript">\nvar sc_project=1657620; \nvar sc_invisible=1; \nvar sc_partition=15; \nvar sc_security="9418eb72"; \nvar sc_text=2; \n</script>\n\n<script type="text/javascript" language="javascript" src="http://www.statcounter.com/counter/counter.js"></script>\n
/***\n|!Name:| ''@@font-size(large):font-variant(small-caps):~ScrollingTabsPlugin@@'' |\n|!Version:|1.0.2|\n|!Location|http://gwsyzygy.googlepages.com/creator.html#ScrollingTabsPlugin|\n|!Del.icio.us|[[click to tag|http://del.icio.us/post?url=http://gwsyzygy.googlepages.com/creator.html%23ScrollingTabsPlugin&title=This+TiddlyWikiPlugin+will+reel+in+those+tabs+on+the+side+that+stretch+on+forever.]]|\n|!Author:|GregWalker |\n|!Type:|Behavior Modification|\n|!Requires|~TW2.x|\n\n!Description\n<<<\nThis plugin will reel in those tabs on the side that stretch on //forever.// Basically, it makes the tabgroup fit the screen and/or the content (display area).\n<<<\n\n!~ToDo\n* Doesn't always resize as it should. Basically it needs to adjust after *any* layout change, which can happen if a slider opens/closes, switch view/edit mode, change to a different stylesheet .... unfortunately such notifications don't exist.\n\n!History\n* 22-May-06, version 1.0.2, cross-brower futzing\n* 26-Apr-06, version 1.0.1, moved scrollbars to inner tab\n* 29-Mar-06, version 1.0.0, initial version\n\n!Code\n***/\n/*{{{*/\nversion.extensions.ScrollingTabsPlugin = { major: 1, minor: 0, revision: 2, date: new Date(2006,5,22),\n source: "http://gwsyzygy.googlepages.com/creator.html#ScrollingTabsPlugin", init: false\n};\n\n// hook up resize event\naddEvent(window, "resize", adjustTabHeight);\n\n// Add adjust call to switchTab core method\nwindow.switchTab_original_gkw = config.macros.tabs.switchTab;\nconfig.macros.tabs.switchTab = function(tabset,tab) {\n window.switchTab_original_gkw(tabset,tab);\n adjustTabHeight();\n}\n\n// utility fxn to get physical location of an element.\n// Technically not necessary; there are findPosX and findPosY methods in core.\nfunction getPos( element )\n{\n var coords = {x: 0, y: 0};\n var el = element;\n while (el) {\n coords.x += el.offsetLeft;\n coords.y += el.offsetTop;\n el = el.offsetParent;\n }\n return coords;\n}\n\nfunction findTabContents(place)\n{\n var theTab = null;\n var scan = [];\n scan.push(place);\n var i=0;\n do\n {\n var nodes = scan[i++].childNodes;\n for(var t=0; t<nodes.length; t++)\n {\n if(nodes[t].className && nodes[t].className == "tabContents")\n {\n theTab = nodes[t];\n scan.push(theTab);\n break;\n }\n else if(nodes[t] && nodes[t].className && nodes[t].className != "tabset" && nodes[t].childNodes && nodes[t].childNodes.length == 2)\n {\n scan.push(nodes[t]);\n }\n }\n } while(i<scan.length);\n\n return (theTab ? theTab : place);\n}\n\n// main function for adjusting tab height.\nfunction adjustTabHeight()\n{\n var sidetabs=document.getElementById("sidebarTabs");\n var disp=document.getElementById("tiddlerDisplay");\n if(sidetabs==null || disp==null) return;\n // locate innermost tab contents\n var tab = findTabContents(sidetabs);\n\n // post-startup init. Some elements do not exist during systemConfig execution.\n if (version.extensions.ScrollingTabsPlugin.init==false)\n {\n version.extensions.ScrollingTabsPlugin.init=true;\n addEvent(sidetabs, "move", adjustTabHeight); // this is not firing when the option panel opens/closes.\n // onchange, onload, onmoveend?\n addEvent(sidetabs, "refresh", adjustTabHeight); // only fires once\n addEvent(sidetabs, "load", adjustTabHeight); // only fires once\n addEvent(sidetabs, "change", adjustTabHeight); // only fires once\n addEvent(disp, "resize", adjustTabHeight); // only fires once\n }\n\n // get physical location of sidebarTabs and displayArea\n // window.innerHeight is viewable area for the body (Mozilla)\n // document.documentElement.clientHeight is viewable area (IE)\n // scrollHeight is desired (e.g. total) height\n // clientHeight is actual height\n // offsetHeight is clientHeight + scrollbar height (if present)\n var pointS = getPos(sidetabs);\n var pointT = getPos(tab);\n var pointD = getPos(disp);\n var winH = (window.innerHeight ? window.innerHeight : document.documentElement.clientHeight);\n /*\n clearMessage();\n displayMessage('client: h=' + winH);\n displayMessage('scroll: h=' + document.body.scrollHeight);\n displayMessage('side: x=' + pointS.x + ' y=' + pointS.y + ' o='+sidetabs.offsetHeight + ' h='+sidetabs.scrollHeight,''); \n displayMessage('tab: x=' + pointT.x + ' y=' + pointT.y + ' o='+tab.offsetHeight + ' h='+tab.scrollHeight,''); \n displayMessage('disp: x=' + pointD.x + ' y=' + pointD.y + ' o='+disp.offsetHeight + ' h='+disp.scrollHeight,''); \n */\n\n // do some mathmatical jiggery-pokery to determine the correct height\n var padding = (sidetabs.offsetHeight - tab.offsetHeight) - (pointT.y - pointS.y);\n padding += 10; // for some reason, this is necessary.\n var avHeight = (disp.scrollHeight + pointD.y);\n avHeight = Math.max(avHeight, winH);\n avHeight -= (pointT.y + padding);\n\n // Adjust for needed space\n if(tab.scrollHeight<avHeight) avHeight=tab.scrollHeight-padding;\n if(avHeight<100) avHeight = 100;\n //displayMessage('final = ' + avHeight,'');\n\n // set the overflow style as appropriate.\n //tab.style.overflow:-moz-scrollbars-vertical position=absolute top=0px bottom=0px\n // http://forums.macosxhints.com/archive/index.php/t-51851.html\n if(tab.style.overflowY != undefined){\n tab.style.overflowY = "auto"; // or scroll (always there)\n } else {\n tab.style["overflow"] = "auto";\n }\n \n // FireFox won't work unless you add "px;" to the height specification. \n // IE doesn't care, but Safari doesn't like it. Stupid browser wars!\n if (config.browser.firefoxDate == null || config.browser.firefoxDate[1] < "20051111")\n tab.style.height=avHeight;\n else\n tab.style.height=avHeight + "px;";\n\n return avHeight;\n }\n\n/*}}}*/\n/***\nThis plugin is released under the [[Creative Commons Attribution 2.5 License|http://creativecommons.org/licenses/by/2.5/]]\n***/\n
<<tabs txtIndex Index Index TabIndex Tags 'All tags' TabTags More 'More...' TabMore>>
/*{{{*/\nconfig.options.chkHttpReadOnly = false; // Enable editing so that visitors can experiment with it \n/*}}}*/
powered by TiddlyWiki, a reusable non-linear personal web notebook
gkwWiki
\n/***\n!!Adjust sidebarTabs for more readable multi-line items.\n***/\n/*{{{*/\n#sidebarTabs .tabContents {\n width: 96%;\n}\n#sidebarTabs .tabContents li {\n text-indent: -10px;\n padding-left: 15px;\n padding-right: 5px;\n word-wrap: word-break;\n list-style: none;\n}\n/*}}}*/\n\n/***\n!!"Ghosted" Toolbars \n***/\n/*{{{*/\n.toolbar { visibility:visible; }\n.toolbar .button { color:#acc; }\n.selected .toolbar { visibility:visible; color:#00f; }\n.selected .toolbar .button { color:#014;}\n/*}}}*/\n\n/***\n!!Stylesheet entries for DisplayTiddlerGlyphsPlugin\n***/\n/*{{{*/\n\n.glyphElement {\n cursor: default;\n}\n.glyphsWrapper {\n padding-right: 3px;\n}\n\n#sidebarTabs li .glyphsWrapper {\n text-indent: -15px;\n}\n\n/*}}}*/
<<listByAuthor>>
<<tabs txtTabIndex \nTimeline 'By Time' TabTimeline \nAuthor 'By Author' TabAuthor \nMine 'Created by Me' TabMine\nAll 'All tiddlers' TabAll>>
Created by me: \n<<listByAuthor creator currentUser>>\n\nModified by me:\n<<listByAuthor modifier currentUser>>\n
Enter any javascript reference and click ''eval'' to get its value:\n<html>\n<input name='fooInput' id='fooInput' size='100%' value='document.title'>\n<input type=button value=eval onClick="document.getElementById('fooOutput').innerHTML = '<pre>' + eval(document.getElementById('fooInput').value) + '</pre>'">\n<div id='fooOutput'></div>\n</html>\n
A hand seldom befriends a widow. The surly debutante greedily avoids contact with the uxorious coward. A lovely bubble plays pinochle with a shadow near an impresario. A looking glass defined by a gypsy barely goes deep sea fishing with a curse defined by the haunch. Now and then, a nefarious widow seldom avoids contact with another debutante living with the toothpick. Indeed, a pocket approaches a hand. Some tea party toward a ruffian has a change of heart about the debutante defined by the pocket. An eagerly unseemly ballerina throws a placid impresario at a taxidermist. Indeed, a pocket living with the shadow secretly graduates from a snow. The Interloper, the friend of Jacques and Mitzi, laughs out loud with the boy beyond the widow. Lila, although somewhat soothed by some gingerly impresario and a clodhopper about the necromancer, still approaches her from a clock from some mirror, greedily bestow great honor upon her the philosopher with a boy, and somewhat laughs and drinks all night with the dark side of her toothache. He called her Nimbo (or was it Toscanini?). When the rapacious dissident dies, a necromancer near a bicep leaves. A pocket toward some fetishist accurately finds subtle faults with a feverishly placid espadrille. A barely darling amour-propre buys an expensive gift for a toothpick around a bicep.
The lunatic toward a bicep is surly. Nicolas and I took the accidentally sprightly tenor (with the necromancer, the dilettante, a few bodice rippers, and the surly bicep) to arrive at a state of intimacy where we can lazily steal pencils from our debutante. A ridiculously comely clock laughs and drinks all night with a knowingly unruffled alchemist. A starlet inside a starlet returns home, and a cup behind a dilettante leaves; however, a guardian angel underhandedly sanitizes an amour-propre. The unruffled omphalos is uxorious. Mitzi, although somewhat soothed by some dilettante living with a dahlia and the bubble, still sanitizes her from the dilettante for the midwife, pour freezing cold water on her a starlet with a self-actualized fetishist, and secretly gives secret financial aid to the dark side of her bride. A toothache related to a looking glass cooks cheese grits for a pocket, and the midwife near a cup ostensibly caricatures the impresario. A girl behind some somnambulist throws a fetishist living with a dilettante at a sheepish omphalos. The bubble toward the dahlia goes to sleep, but the botched toothpick buys an expensive gift for a fetishist. A dahlia pours freezing cold water on a piroshki near the pocket. A trombone has a change of heart about the carelessly nefarious fetishist. Unlike so many toothpicks who have made their greedily rascally bubble abhorrent to us, curses remain surly. A bubble around the bubble often negotiates a prenuptial agreement with some clock. Most people believe that the stalactite recognizes another lunatic from a waif, but they need to remember how single-handledly the bubble trembles.
See StyleSheet
These entries were created with the wonderful //Transitive Vampire Text Generator//, which sadly seems to be no more. It used to be [[here|http://javascript.internet.com/messages/sentence.html]], but the original is gone. However it seems to have been [[reborn|http://jeffcarr.info/programs/randomtext/]]!