PageRenderTime 67ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/rdbms/doc/rdbms.html

http://github.com/gebi/jungerl
HTML | 4272 lines | 4045 code | 194 blank | 33 comment | 0 complexity | 717ff9ac828a9d56723462f69c458b51 MD5 | raw file
Possible License(s): AGPL-1.0, JSON, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <script type="text/javascript">
  3. var version = {major: 1, minor: 2, revision: 32, date: new Date("Aug 18, 2005"), extensions: {}};
  4. </script>
  5. <!--
  6. TiddlyWiki 1.2.32 by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
  7. Published under a BSD open source license
  8. Incorporating improvements by Isao Sonobe, http://www-gauge.scphys.kyoto-u.ac.jp/~sonobe/OgreKit/OgreKitWiki.html
  9. Copyright (c) Osmosoft Limited, 14 April 2005
  10. Redistribution and use in source and binary forms, with or without modification,
  11. are permitted provided that the following conditions are met:
  12. Redistributions of source code must retain the above copyright notice, this
  13. list of conditions and the following disclaimer.
  14. Redistributions in binary form must reproduce the above copyright notice, this
  15. list of conditions and the following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. Neither the name of the Osmosoft Limited nor the names of its contributors may be
  18. used to endorse or promote products derived from this software without specific
  19. prior written permission.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  21. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  22. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  23. SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  25. TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  26. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  28. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  29. DAMAGE.
  30. -->
  31. <html>
  32. <head>
  33. <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  34. <title>RDBMS</title>
  35. <script type="text/javascript">
  36. // ---------------------------------------------------------------------------------
  37. // Configuration repository
  38. // ---------------------------------------------------------------------------------
  39. var config = {
  40. // Options that can be set in the options panel and/or cookies
  41. options: {
  42. chkRegExpSearch: false,
  43. chkCaseSensitiveSearch: false,
  44. chkAnimate: true,
  45. txtUserName: "YourName",
  46. chkSaveBackups: true,
  47. chkAutoSave: false,
  48. chkGenerateAnRssFeed: false,
  49. chkSaveEmptyTemplate: false,
  50. chkOpenInNewWindow: true,
  51. chkToggleLinks: false,
  52. chkHttpReadOnly: false,
  53. txtMainTab: "tabTimeline",
  54. txtMoreTab: "moreTabAll"
  55. },
  56. // Hashmap of notification functions to be called when certain tiddlers are changed or deleted
  57. notifyNamedTiddlers: {
  58. SiteTitle: refreshTitle,
  59. SiteSubtitle: refreshSubtitle,
  60. SideBarOptions: refreshSidebar,
  61. StyleSheet: refreshStyles
  62. },
  63. // List of notification functions to be called when any tiddler is changed or deleted
  64. notifyTiddlers: [
  65. refreshMenu,
  66. refreshStory,
  67. refreshTabs
  68. ],
  69. // Shadow tiddlers for emergencies
  70. shadowTiddlers: {
  71. SideBarOptions: "<<search>><<closeAll>><<permaview>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel options 'Change TiddlyWiki advanced options'>>",
  72. OptionsPanel: "These InterfaceOptions for customising TiddlyWiki are saved in your browser\n\nYour username for signing your edits. Write it as a WikiWord (eg JoeBloggs)\n\n<<option txtUserName>>\n<<option chkSaveBackups>> SaveBackups\n<<option chkAutoSave>> AutoSave\n<<option chkGenerateAnRssFeed>> GenerateAnRssFeed\n<<option chkRegExpSearch>> RegExpSearch\n<<option chkCaseSensitiveSearch>> CaseSensitiveSearch\n<<option chkAnimate>> EnableAnimations\n\nSee AdvancedOptions",
  73. AdvancedOptions: "<<option chkOpenInNewWindow>> OpenLinksInNewWindow\n<<option chkSaveEmptyTemplate>> SaveEmptyTemplate\n<<option chkToggleLinks>> Clicking on links to tiddlers that are already open causes them to close\n^^(override with Control or other modifier key)^^\n<<option chkHttpReadOnly>> HideEditingFeatures when viewed over HTTP",
  74. SideBarTabs: "<<tabs txtMainTab Timeline Timeline TabTimeline All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>",
  75. TabTimeline: "<<timeline>>",
  76. TabAll: "<<list all>>",
  77. TabTags: "<<allTags>>",
  78. TabMore: "<<tabs txtMoreTab Missing 'Missing tiddlers' TabMoreMissing Orphans 'Orphaned tiddlers' TabMoreOrphans>>",
  79. TabMoreMissing: "<<list missing>>",
  80. TabMoreOrphans: "<<list orphans>>"
  81. },
  82. // Miscellaneous options
  83. numRssItems: 20, // Number of items in the RSS feed
  84. animFast: 0.12, // Speed for animations (lower == slower)
  85. animSlow: 0.01, // Speed for EasterEgg animations
  86. // Messages
  87. messages: {
  88. customConfigError: "Error in customConfig - %0",
  89. savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see http://www.tiddlywiki.com/#DownloadSoftware for details",
  90. subtitleUnknown: "(unknown)",
  91. undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
  92. externalLinkTooltip: "External link to %0",
  93. noTags: "There are no tagged tiddlers",
  94. notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
  95. cantSaveError: "It's not possible to save changes using this browser. Use FireFox if you can",
  96. invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
  97. backupSaved: "Backup saved",
  98. backupFailed: "Failed to save backup file",
  99. rssSaved: "RSS feed saved",
  100. rssFailed: "Failed to save RSS feed file",
  101. emptySaved: "Empty template saved",
  102. emptyFailed: "Failed to save empty template file",
  103. mainSaved: "Main TiddlyWiki file saved",
  104. mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
  105. macroError: "Error executing macro '%0'",
  106. overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
  107. unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
  108. dates: {
  109. months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"],
  110. days: ["Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
  111. }
  112. },
  113. views: {
  114. wikified: {
  115. tag: {labelNoTags: "no tags", labelTags: "tags: ", tooltip: "Show tiddlers tagged with '%0'", openAllText: "Open all", openAllTooltip: "Open all of these tiddlers", popupNone: "No other tiddlers tagged with '%0'"},
  116. toolbarClose: {text: "close", tooltip: "Close this tiddler"},
  117. toolbarEdit: {text: "edit", tooltip: "Edit this tiddler"},
  118. toolbarPermalink: {text: "permalink", tooltip: "Permalink for this tiddler"},
  119. toolbarReferences: {text: "references", tooltip: "Show tiddlers that link to this one", popupNone: "No references"},
  120. defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it"
  121. },
  122. editor: {
  123. tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
  124. tagChooser: {text: "tags", tooltip: "Choose existing tags to add to this tiddler", popupNone: "There are no tags defined", tagTooltip: "Add the tag '%0'"},
  125. toolbarDone: {text: "done", tooltip: "Save changes to this tiddler"},
  126. toolbarCancel: {text: "cancel", tooltip: "Undo changes to this tiddler"},
  127. toolbarDelete: {text: "delete", tooltip: "Delete this tiddler"},
  128. defaultText: "Type the text for '%0'"
  129. }
  130. },
  131. macros: { // Each has a 'handler' member that is inserted later
  132. today: {},
  133. version: {},
  134. search: {label: "search", prompt: "Search this TiddlyWiki", sizeTextbox: 15, successMsg: "%0 tiddlers found matching %1", failureMsg: "No tiddlers found matching %0"},
  135. tiddler: {},
  136. tag: {},
  137. timeline: {dateFormat: "DD MMM YYYY"},
  138. allTags: {tooltip: "Show tiddlers tagged with '%0'", noTags: "There are no tagged tiddlers"},
  139. list: {
  140. all: {prompt: "All tiddlers in alphabetical order"},
  141. missing: {prompt: "Tiddlers that have links to them but are not defined"},
  142. orphans: {prompt: "Tiddlers that are not linked to from any other tiddlers"}
  143. },
  144. closeAll: {label: "close all", prompt: "Close all displayed tiddlers (except any that are being edited)"},
  145. permaview: {label: "permaview", prompt: "Link to an URL that retrieves all the currently displayed tiddlers"},
  146. saveChanges: {label: "save changes", prompt: "Save all tiddlers to create a new TiddlyWiki"},
  147. slider: {},
  148. option: {},
  149. newTiddler: {label: "new tiddler", prompt: "Create a new tiddler", title: "New Tiddler"},
  150. newJournal: {label: "new journal", prompt: "Create a new tiddler from the current date and time"},
  151. sparkline: {},
  152. tabs: {}
  153. }
  154. };
  155. // ---------------------------------------------------------------------------------
  156. // Main
  157. // ---------------------------------------------------------------------------------
  158. // TiddlyWiki storage
  159. var store = new TiddlyWiki();
  160. // Animation engine
  161. var anim = new Animator();
  162. var readOnly = false;
  163. // Starting up
  164. function main()
  165. {
  166. setupRegexp();
  167. saveTest();
  168. loadOptionsCookie();
  169. var s;
  170. for(s in config.notifyNamedTiddlers)
  171. store.addNotification(s,config.notifyNamedTiddlers[s]);
  172. for(s=0; s<config.notifyTiddlers.length; s++)
  173. store.addNotification(null,config.notifyTiddlers[s]);
  174. store.loadFromDiv("storeArea","store");
  175. loadSystemConfig();
  176. readOnly = (document.location.toString().substr(0,7) == "http://") ? config.options.chkHttpReadOnly : false;
  177. store.notifyAll();
  178. var start = store.getTiddlerText("DefaultTiddlers");
  179. if(window.location.hash)
  180. displayTiddlers(null,convertUTF8ToUnicode(decodeURI(window.location.hash.substr(1))),1,null,null);
  181. else if(start)
  182. displayTiddlers(null,start,1,null,null);
  183. }
  184. function saveTest()
  185. {
  186. var saveTest = document.getElementById("saveTest");
  187. if(saveTest.hasChildNodes())
  188. alert(config.messages.savedSnapshotError);
  189. saveTest.appendChild(document.createTextNode("savetest"));
  190. }
  191. function loadSystemConfig()
  192. {
  193. var configTiddlers = store.getTaggedTiddlers("systemConfig");
  194. for(var t=0; t<configTiddlers.length; t++)
  195. {
  196. var ex = processConfig(configTiddlers[t].text);
  197. if(ex)
  198. displayMessage(config.messages.customConfigError.format([ex]));
  199. }
  200. }
  201. // ---------------------------------------------------------------------------------
  202. // Macro definitions
  203. // ---------------------------------------------------------------------------------
  204. config.macros.today.handler = function(place)
  205. {
  206. createTiddlyElement(place,"span",null,null,(new Date()).toLocaleString());
  207. }
  208. config.macros.version.handler = function(place)
  209. {
  210. createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision);
  211. }
  212. config.macros.list.handler = function(place,macroName,params)
  213. {
  214. var type = params[0] ? params[0] : "all";
  215. var theList = document.createElement("ul");
  216. place.appendChild(theList);
  217. if(this[type].prompt)
  218. createTiddlyElement(theList,"li",null,"listTitle",this[type].prompt);
  219. var results;
  220. if(this[type].handler)
  221. results = this[type].handler(params);
  222. for (t = 0; t < results.length; t++)
  223. {
  224. theListItem = document.createElement("li")
  225. theList.appendChild(theListItem);
  226. if(typeof results[t] == "string")
  227. createTiddlyLink(theListItem,results[t],true);
  228. else
  229. createTiddlyLink(theListItem,results[t].title,true);
  230. }
  231. }
  232. config.macros.list.all.handler = function(params)
  233. {
  234. return store.reverseLookup("tags","excludeLists",false,"title");
  235. }
  236. config.macros.list.missing.handler = function(params)
  237. {
  238. return store.getMissingLinks();
  239. }
  240. config.macros.list.orphans.handler = function(params)
  241. {
  242. return store.getOrphans();
  243. }
  244. config.macros.allTags.handler = function(place,macroName,params)
  245. {
  246. var tags = store.getTags();
  247. var theDateList = createTiddlyElement(place,"ul",null,null,null);
  248. if(tags.length == 0)
  249. createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);
  250. for (t=0; t<tags.length; t++)
  251. {
  252. var theListItem =createTiddlyElement(theDateList,"li",null,null,null);
  253. var theTag = createTiddlyButton(theListItem,tags[t][0] + " (" + tags[t][1] + ")",this.tooltip.format([tags[t][0]]),onClickTag);
  254. theTag.setAttribute("tag",tags[t][0]);
  255. }
  256. }
  257. config.macros.timeline.handler = function(place,macroName,params)
  258. {
  259. var tiddlers = store.reverseLookup("tags","excludeLists",false,"modified");
  260. var lastDay = "";
  261. for (t=tiddlers.length-1; t>=0; t--)
  262. {
  263. var tiddler = tiddlers[t];
  264. var theDay = tiddler.modified.convertToYYYYMMDDHHMM().substr(0,8);
  265. if(theDay != lastDay)
  266. {
  267. var theDateList = document.createElement("ul");
  268. place.appendChild(theDateList);
  269. createTiddlyElement(theDateList,"li",null,"listTitle",tiddler.modified.formatString(this.dateFormat));
  270. lastDay = theDay;
  271. }
  272. var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink",null);
  273. theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
  274. }
  275. }
  276. config.macros.search.handler = function(place,macroName,params)
  277. {
  278. var lastSearchText = "";
  279. var searchTimeout = null;
  280. var doSearch = function(txt)
  281. {
  282. closeAllTiddlers();
  283. var matches = store.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch,"title","excludeSearch");
  284. for(var t=matches.length-1; t>=0; t--)
  285. displayTiddler(null,matches[t].title,0,txt.value,config.options.chkCaseSensitiveSearch,false,false);
  286. var q = config.options.chkRegExpSearch ? "/" : "'";
  287. if(matches.length > 0)
  288. displayMessage(config.macros.search.successMsg.format([matches.length.toString(),q + txt.value + q]));
  289. else
  290. displayMessage(config.macros.search.failureMsg.format([q + txt.value + q]));
  291. lastSearchText = txt.value;
  292. };
  293. var clickHandler = function(e)
  294. {
  295. doSearch(this.nextSibling);
  296. };
  297. var keyHandler = function(e)
  298. {
  299. if (!e) var e = window.event;
  300. switch(e.keyCode)
  301. {
  302. case 27:
  303. this.value = "";
  304. clearMessage();
  305. break;
  306. }
  307. if((this.value.length > 2) && (this.value != lastSearchText))
  308. {
  309. if(searchTimeout)
  310. clearTimeout(searchTimeout);
  311. var txt = this;
  312. searchTimeout = setTimeout(function() {doSearch(txt);},200);
  313. }
  314. };
  315. var focusHandler = function(e)
  316. {
  317. this.select();
  318. };
  319. var btn = createTiddlyButton(place,this.label,this.prompt,clickHandler);
  320. var txt = createTiddlyElement(place,"input",null,null,null);
  321. if(params[0])
  322. txt.value = params[0];
  323. txt.onkeyup = keyHandler;
  324. txt.onfocus = focusHandler;
  325. txt.setAttribute("size",this.sizeTextbox);
  326. txt.setAttribute("autocomplete","off");
  327. if(navigator.userAgent.toLowerCase().indexOf("safari") == -1)
  328. txt.setAttribute("type","text");
  329. else
  330. {
  331. txt.setAttribute("type","search");
  332. txt.setAttribute("results","5");
  333. }
  334. }
  335. config.macros.tiddler.handler = function(place,macroName,params)
  336. {
  337. var wrapper = createTiddlyElement(place,"span",null,params[1] ? params[1] : null,null);
  338. var text = store.getTiddlerText(params[0]);
  339. if(text)
  340. wikify(text,wrapper,null,null);
  341. }
  342. config.macros.tag.handler = function(place,macroName,params)
  343. {
  344. createTagButton(place,params[0]);
  345. }
  346. config.macros.closeAll.handler = function(place)
  347. {
  348. createTiddlyButton(place,this.label,this.prompt,closeAllTiddlers);
  349. }
  350. config.macros.permaview.handler = function(place)
  351. {
  352. createTiddlyButton(place,this.label,this.prompt,onClickPermaView);
  353. }
  354. config.macros.saveChanges.handler = function(place)
  355. {
  356. if(!readOnly)
  357. createTiddlyButton(place,this.label,this.prompt,saveChanges);
  358. }
  359. config.macros.slider.onClickSlider = function(e)
  360. {
  361. if (!e) var e = window.event;
  362. var n = this.nextSibling;
  363. var cookie = n.getAttribute("cookie");
  364. var isOpen = n.style.display != "none";
  365. if(config.options.chkAnimate)
  366. anim.startAnimating(new Slider(n,!isOpen,e.shiftKey || e.altKey,"none"));
  367. else
  368. n.style.display = isOpen ? "none" : "block";
  369. config.options[cookie] = !isOpen;
  370. saveOptionCookie(cookie);
  371. }
  372. config.macros.slider.handler = function(place,macroName,params)
  373. {
  374. var cookie = params[0] ? params[0] : "";
  375. var text = store.getTiddlerText(params[1]);
  376. var btn = createTiddlyButton(place,params[2],params[3],this.onClickSlider);
  377. var panel = createTiddlyElement(place,"div",null,"sliderPanel",null);
  378. panel.setAttribute("cookie",cookie);
  379. panel.style.display = config.options[cookie] ? "block" : "none";
  380. if(text)
  381. wikify(text,panel,null,null);
  382. }
  383. config.macros.option.onChangeOption = function(e)
  384. {
  385. var opt = this.getAttribute("option");
  386. var elementType,valueField;
  387. if(opt)
  388. {
  389. switch(opt.substr(0,3))
  390. {
  391. case "txt":
  392. elementType = "input";
  393. valueField = "value";
  394. break;
  395. case "chk":
  396. elementType = "input";
  397. valueField = "checked";
  398. break;
  399. }
  400. config.options[opt] = this[valueField];
  401. saveOptionCookie(opt);
  402. var nodes = document.getElementsByTagName(elementType);
  403. for(var t=0; t<nodes.length; t++)
  404. {
  405. var optNode = nodes[t].getAttribute("option");
  406. if(opt == optNode)
  407. nodes[t][valueField] = this[valueField];
  408. }
  409. }
  410. return(true);
  411. }
  412. config.macros.option.handler = function(place,macroName,params)
  413. {
  414. var opt = params[0];
  415. if(config.options[opt] == undefined)
  416. return;
  417. var c;
  418. switch(opt.substr(0,3))
  419. {
  420. case "txt":
  421. c = document.createElement("input");
  422. c.onkeyup = this.onChangeOption;
  423. c.setAttribute("option",opt);
  424. c.size = 15;
  425. c.value = config.options[opt];
  426. place.appendChild(c);
  427. break;
  428. case "chk":
  429. c = document.createElement("input");
  430. c.setAttribute("type","checkbox");
  431. c.onclick = this.onChangeOption;
  432. c.setAttribute("option",opt);
  433. c.checked = config.options[opt];
  434. place.appendChild(c);
  435. break;
  436. }
  437. }
  438. config.macros.newTiddler.onClick = function()
  439. {
  440. displayTiddler(null,config.macros.newTiddler.title,2,null,null,false,false);
  441. var e = document.getElementById("editorTitle" + config.macros.newTiddler.title);
  442. e.focus();
  443. e.select();
  444. }
  445. config.macros.newTiddler.handler = function(place)
  446. {
  447. if(!readOnly)
  448. createTiddlyButton(place,this.label,this.prompt,this.onClick);
  449. }
  450. config.macros.newJournal.handler = function(place,macroName,params)
  451. {
  452. if(!readOnly)
  453. {
  454. var now = new Date();
  455. var title = now.formatString(params[0].trim());
  456. var createJournal = function() {
  457. displayTiddler(null,title,2,null,null,false,false);
  458. var tagsBox = document.getElementById("editorTags" + title);
  459. if(tagsBox && params[1])
  460. tagsBox.value += " " + String.encodeTiddlyLink(params[1]);
  461. };
  462. createTiddlyButton(place,this.label,this.prompt,createJournal);
  463. }
  464. }
  465. config.macros.sparkline.handler = function(place,macroName,params)
  466. {
  467. var data = [];
  468. var min = 0;
  469. var max = 0;
  470. for(var t=0; t<params.length; t++)
  471. {
  472. var v = parseInt(params[t]);
  473. if(v < min)
  474. min = v;
  475. if(v > max)
  476. max = v;
  477. data.push(v);
  478. }
  479. if(data.length < 1)
  480. return;
  481. var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
  482. box.title = data.join(",");
  483. var w = box.offsetWidth;
  484. var h = box.offsetHeight;
  485. box.style.paddingRight = (data.length * 2 - w) + "px";
  486. box.style.position = "relative";
  487. for(var d=0; d<data.length; d++)
  488. {
  489. var tick = document.createElement("img");
  490. tick.border = 0;
  491. tick.className = "sparktick";
  492. tick.style.position = "absolute";
  493. tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
  494. tick.style.left = d*2 + "px";
  495. tick.style.width = "2px";
  496. var v = Math.floor(((data[d] - min)/(max-min)) * h);
  497. tick.style.top = (h-v) + "px";
  498. tick.style.height = v + "px";
  499. box.appendChild(tick);
  500. }
  501. }
  502. config.macros.tabs.handler = function(place,macroName,params)
  503. {
  504. var cookie = params[0];
  505. var numTabs = (params.length-1)/3;
  506. var wrapper = createTiddlyElement(place,"div",null,cookie,null);
  507. var tabset = createTiddlyElement(wrapper,"div",null,"tabset",null);
  508. tabset.setAttribute("cookie",cookie);
  509. var validTab = false;
  510. for(var t=0; t<numTabs; t++)
  511. {
  512. var label = params[t*3+1];
  513. var prompt = params[t*3+2];
  514. var content = params[t*3+3];
  515. var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,"tab tabUnselected");
  516. tab.setAttribute("href","javascript:;");
  517. tab.onclick = this.onClickTab;
  518. tab.setAttribute("tab",label);
  519. tab.setAttribute("content",content);
  520. tab.title = prompt;
  521. if(config.options[cookie] == label)
  522. validTab = true;
  523. }
  524. if(!validTab)
  525. config.options[cookie] = params[1];
  526. this.switchTab(tabset,config.options[cookie]);
  527. }
  528. config.macros.tabs.onClickTab = function(e)
  529. {
  530. config.macros.tabs.switchTab(this.parentNode,this.getAttribute("tab"));
  531. }
  532. config.macros.tabs.switchTab = function(tabset,tab)
  533. {
  534. var cookie = tabset.getAttribute("cookie");
  535. var theTab = null
  536. var nodes = tabset.childNodes;
  537. for(var t=0; t<nodes.length; t++)
  538. if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
  539. {
  540. theTab = nodes[t];
  541. theTab.className = "tab tabSelected";
  542. }
  543. else
  544. nodes[t].className = "tab tabUnselected"
  545. if(theTab)
  546. {
  547. if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
  548. tabset.parentNode.removeChild(tabset.nextSibling);
  549. var tabContent = createTiddlyElement(null,"div",null,"tabContents",null);
  550. tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
  551. wikify(store.getTiddlerText(theTab.getAttribute("content")),tabContent,null,null);
  552. if(cookie)
  553. {
  554. config.options[cookie] = tab;
  555. saveOptionCookie(cookie);
  556. }
  557. }
  558. }
  559. // ---------------------------------------------------------------------------------
  560. // Config and macro stuff
  561. // ---------------------------------------------------------------------------------
  562. // Merge a custom configuration over the top of the current configuration
  563. // Returns a string error message or null if it went OK
  564. function processConfig(customConfig)
  565. {
  566. try
  567. {
  568. if(customConfig && customConfig != "")
  569. window.eval(customConfig);
  570. }
  571. catch(e)
  572. {
  573. return(e.toString());
  574. }
  575. return null;
  576. }
  577. // Render a macro
  578. function insertMacro(place,macroName,macroParams)
  579. {
  580. var params = macroParams.readMacroParams();
  581. try
  582. {
  583. var macro = config.macros[macroName];
  584. if(macro && macro.handler)
  585. macro.handler(place,macroName,params);
  586. else
  587. createTiddlyElement(place,"span",null,"errorNoSuchMacro","<<" + macroName + ">>");
  588. }
  589. catch(e)
  590. {
  591. displayMessage(config.messages.macroError.format([macroName]));
  592. displayMessage(e.toString());
  593. }
  594. }
  595. // ---------------------------------------------------------------------------------
  596. // Tiddler() object
  597. // ---------------------------------------------------------------------------------
  598. function Tiddler()
  599. {
  600. this.title = null;
  601. this.text = null;
  602. this.modifier = null;
  603. this.modified = new Date();
  604. this.links = [];
  605. this.tags = [];
  606. return this;
  607. }
  608. // Load a tiddler from an HTML DIV
  609. Tiddler.prototype.loadFromDiv = function(divRef,title)
  610. {
  611. var text = Tiddler.unescapeLineBreaks(divRef.firstChild ? divRef.firstChild.nodeValue : "");
  612. var modifier = divRef.getAttribute("modifier");
  613. var modified = Date.convertFromYYYYMMDDHHMM(divRef.getAttribute("modified"));
  614. var tags = divRef.getAttribute("tags");
  615. this.set(title,text,modifier,modified,tags);
  616. return this;
  617. }
  618. // Format the text for storage in an HTML DIV
  619. Tiddler.prototype.saveToDiv = function()
  620. {
  621. return '<div tiddler="' + this.title + '" modified="' +
  622. this.modified.convertToYYYYMMDDHHMM() + '" modifier="' + this.modifier +
  623. '" tags="' + this.getTags() + '">' +
  624. this.escapeLineBreaks().htmlEncode() + '</div>';
  625. }
  626. // Format the text for storage in an RSS item
  627. Tiddler.prototype.saveToRss = function(url)
  628. {
  629. var s = [];
  630. s.push("<item>");
  631. s.push("<title>" + this.title.htmlEncode() + "</title>");
  632. s.push("<description>" + this.text.replace(regexpNewLine,"<br />").htmlEncode() + "</description>");
  633. for(var t=0; t<this.tags.length; t++)
  634. s.push("<category>" + this.tags[t] + "</category>");
  635. s.push("<link>" + url + "#" + encodeURIComponent(String.encodeTiddlyLink(this.title)) + "</link>");
  636. s.push("<pubDate>" + this.modified.toGMTString() + "</pubDate>");
  637. s.push("</item>");
  638. return(s.join("\n"));
  639. }
  640. // Change the text and other attributes of a tiddler
  641. Tiddler.prototype.set = function(title,text,modifier,modified,tags)
  642. {
  643. if(title != undefined)
  644. this.title = title;
  645. if(text != undefined)
  646. this.text = text;
  647. if(modifier != undefined)
  648. this.modifier = modifier;
  649. if(modified != undefined)
  650. this.modified = modified;
  651. if(tags != undefined)
  652. this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags;
  653. else
  654. this.tags = [];
  655. this.changed();
  656. return this;
  657. }
  658. // Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces)
  659. Tiddler.prototype.getTags = function()
  660. {
  661. if(this.tags)
  662. {
  663. var results = [];
  664. for(var t=0; t<this.tags.length; t++)
  665. results.push(String.encodeTiddlyLink(this.tags[t]));
  666. return results.join(" ");
  667. }
  668. else
  669. return "";
  670. }
  671. var regexpBackSlashEn = new RegExp("\\\\n","mg");
  672. var regexpBackSlash = new RegExp("\\\\","mg");
  673. var regexpBackSlashEss = new RegExp("\\\\s","mg");
  674. var regexpNewLine = new RegExp("\n","mg");
  675. var regexpCarriageReturn = new RegExp("\r","mg");
  676. // Static method to Convert "\n" to newlines, "\s" to "\"
  677. Tiddler.unescapeLineBreaks = function(text)
  678. {
  679. if(text && text != "")
  680. return text.replace(regexpBackSlashEn,"\n").replace(regexpBackSlashEss,"\\").replace(regexpCarriageReturn,"");
  681. else
  682. return "";
  683. }
  684. // Convert newlines to "\n", "\" to "\s"
  685. Tiddler.prototype.escapeLineBreaks = function()
  686. {
  687. return this.text.replace(regexpBackSlash,"\\s").replace(regexpNewLine,"\\n").replace(regexpCarriageReturn,"");
  688. }
  689. // Updates the secondary information (like links[] array) after a change to a tiddler
  690. Tiddler.prototype.changed = function()
  691. {
  692. this.links = [];
  693. var nextPos = 0;
  694. var theLink;
  695. do {
  696. var formatMatch = wikiNameRegExp.exec(this.text);
  697. if(formatMatch)
  698. {
  699. if(!formatMatch[1] && formatMatch[2] && formatMatch[2] != this.title)
  700. this.links.pushUnique(formatMatch[2]);
  701. else if(formatMatch[4] && store.tiddlers[formatMatch[5]] != undefined)
  702. this.links.pushUnique(formatMatch[5]);
  703. else if(formatMatch[6] && formatMatch[6] != this.title)
  704. this.links.pushUnique(formatMatch[6]);
  705. }
  706. } while(formatMatch);
  707. return;
  708. }
  709. Tiddler.prototype.getSubtitle = function()
  710. {
  711. var theModifier = this.modifier;
  712. if(!theModifier)
  713. theModifier = config.messages.subtitleUnknown;
  714. var theModified = this.modified;
  715. if(theModified)
  716. theModified = theModified.toLocaleString();
  717. else
  718. theModified = config.messages.subtitleUnknown;
  719. return(theModifier + ", " + theModified);
  720. }
  721. // ---------------------------------------------------------------------------------
  722. // TiddlyWiki() object contains Tiddler()s
  723. // ---------------------------------------------------------------------------------
  724. function TiddlyWiki()
  725. {
  726. this.tiddlers = {}; // Hashmap by name of tiddlers
  727. this.namedNotifications = {}; // Hashmap by name of array of notification functions
  728. this.blanketNotifications = []; // Array of blanket notifications to be invoked on any change
  729. this.dirty = false;
  730. }
  731. // Set the dirty flag
  732. TiddlyWiki.prototype.setDirty = function(dirty)
  733. {
  734. this.dirty = dirty;
  735. }
  736. // Invoke the notification handlers for a particular tiddler
  737. TiddlyWiki.prototype.notify = function(title,doBlanket)
  738. {
  739. var notification = this.namedNotifications[title];
  740. if(notification)
  741. for(var t=0; t<notification.length; t++)
  742. notification[t](title);
  743. if(doBlanket)
  744. for(var n=0; n<this.blanketNotifications.length; n++)
  745. this.blanketNotifications[n](title);
  746. }
  747. // Invoke the notification handlers for all tiddlers
  748. TiddlyWiki.prototype.notifyAll = function()
  749. {
  750. var notifyTitle;
  751. for(notifyTitle in this.tiddlers)
  752. this.notify(notifyTitle,false);
  753. for(notifyTitle in config.shadowTiddlers)
  754. if(this.tiddlers[notifyTitle] == undefined)
  755. this.notify(notifyTitle,false);
  756. for(var n=0; n<this.blanketNotifications.length; n++)
  757. this.blanketNotifications[n]();
  758. }
  759. // Add a notification handler to a tiddler
  760. TiddlyWiki.prototype.addNotification = function(title,fn)
  761. {
  762. var notification;
  763. if(title)
  764. {
  765. notification = this.namedNotifications[title];
  766. if(!notification)
  767. {
  768. notification = [];
  769. this.namedNotifications[title] = notification;
  770. }
  771. }
  772. else
  773. notification = this.blanketNotifications;
  774. notification.push(fn);
  775. return this;
  776. }
  777. // Clear a TiddlyWiki so that it contains no tiddlers
  778. TiddlyWiki.prototype.clear = function(src)
  779. {
  780. this.tiddlers = {};
  781. this.dirty = false;
  782. }
  783. TiddlyWiki.prototype.removeTiddler = function(title)
  784. {
  785. var tiddler = this.tiddlers[title];
  786. if(tiddler)
  787. {
  788. delete this.tiddlers[title];
  789. this.notify(title,true);
  790. this.dirty = true;
  791. }
  792. }
  793. TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
  794. {
  795. if(!title)
  796. return(defaultText);
  797. var tiddler = this.tiddlers[title];
  798. if(tiddler)
  799. return tiddler.text;
  800. else if(config.shadowTiddlers[title])
  801. return config.shadowTiddlers[title];
  802. else if(defaultText)
  803. return defaultText;
  804. else
  805. return null;
  806. }
  807. TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,ignoreList)
  808. {
  809. var childIgnoreList = ignoreList ? ignoreList : {};
  810. childIgnoreList[title] = true;
  811. var bracketRegExp = new RegExp("(?:\\[\\[([^\\]]+)\\]\\])","mg");
  812. var text = this.getTiddlerText(title,defaultText);
  813. if(text == null)
  814. return "";
  815. var textOut = [];
  816. var lastPos = 0;
  817. do {
  818. var match = bracketRegExp.exec(text);
  819. if(match)
  820. {
  821. textOut.push(text.substr(lastPos,match.index-lastPos));
  822. if(match[1])
  823. {
  824. if(childIgnoreList[match[1]])
  825. textOut.push(match[1]);
  826. else
  827. {
  828. var subText = this.getRecursiveTiddlerText(match[1],match[1],childIgnoreList);
  829. textOut.push(subText);
  830. }
  831. }
  832. lastPos = match.index + match[1].length + 4;
  833. }
  834. else
  835. textOut.push(text.substr(lastPos));
  836. } while(match);
  837. delete childIgnoreList[title];
  838. return(textOut.join(""));
  839. }
  840. TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags)
  841. {
  842. var tiddler = this.tiddlers[title];
  843. if(tiddler)
  844. delete this.tiddlers[title];
  845. else
  846. tiddler = new Tiddler();
  847. tiddler.set(newTitle,newBody,modifier,modified,tags);
  848. this.tiddlers[newTitle] = tiddler;
  849. if(title != newTitle)
  850. this.notify(title,true);
  851. this.notify(newTitle,true);
  852. this.dirty = true;
  853. return tiddler;
  854. }
  855. TiddlyWiki.prototype.createTiddler = function(title)
  856. {
  857. tiddler = this.tiddlers[title];
  858. if(!tiddler)
  859. {
  860. tiddler = new Tiddler();
  861. this.tiddlers[title] = tiddler;
  862. this.dirty = true;
  863. }
  864. return tiddler;
  865. }
  866. // Load contents of a tiddlywiki from an HTML DIV
  867. TiddlyWiki.prototype.loadFromDiv = function(srcID,idPrefix)
  868. {
  869. if(document.normalize)
  870. document.normalize();
  871. var lenPrefix = idPrefix.length;
  872. var store = document.getElementById(srcID).childNodes;
  873. for(var t = 0; t < store.length; t++)
  874. {
  875. var e = store[t];
  876. var title = null;
  877. if(e.getAttribute)
  878. title = e.getAttribute("tiddler");
  879. if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
  880. title = e.id.substr(lenPrefix);
  881. if(title && title != "")
  882. {
  883. var tiddler = this.createTiddler(title);
  884. tiddler.loadFromDiv(e,title);
  885. }
  886. }
  887. this.dirty = false;
  888. }
  889. // Return an array of tiddlers matching a search string
  890. TiddlyWiki.prototype.search = function(searchText,caseSensitive,useRegExp,sortField,excludeTag)
  891. {
  892. if (!useRegExp)
  893. searchText = searchText.escapeRegExp();
  894. var regExp = new RegExp(searchText,caseSensitive ? "m" : "im");
  895. var candidates = this.reverseLookup("tags",excludeTag,false);
  896. var results = [];
  897. for(var t=0; t<candidates.length; t++)
  898. {
  899. if(regExp.test(candidates[t].title) || regExp.test(candidates[t].text))
  900. results.push(candidates[t]);
  901. }
  902. if(!sortField)
  903. sortField = "title";
  904. results.sort(function (a,b) {if(a[sortField] == b[sortField]) return(0); else return (a[sortField] < b[sortField]) ? -1 : +1; });
  905. return results;
  906. }
  907. // Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances
  908. TiddlyWiki.prototype.getTags = function()
  909. {
  910. var results = [];
  911. for(var t in this.tiddlers)
  912. {
  913. var tiddler = this.tiddlers[t];
  914. for(g=0; g<tiddler.tags.length; g++)
  915. {
  916. var tag = tiddler.tags[g];
  917. var f = false;
  918. for(var c=0; c<results.length; c++)
  919. if(results[c][0] == tag)
  920. {
  921. f = true;
  922. results[c][1]++;
  923. }
  924. if(!f)
  925. results.push([tag,1]);
  926. }
  927. }
  928. results.sort(function (a,b) {if(a[0] == b[0]) return(0); else return (a[0] < b[0]) ? -1 : +1; });
  929. return results;
  930. }
  931. // Return an array of the tiddlers that are tagged with a given tag
  932. TiddlyWiki.prototype.getTaggedTiddlers = function(tag,sortField)
  933. {
  934. return this.reverseLookup("tags",tag,true,sortField);
  935. }
  936. // Return an array of the tiddlers that link to a given tiddler
  937. TiddlyWiki.prototype.getReferringTiddlers = function(title,exclude,sortField)
  938. {
  939. return this.reverseLookup("links",title,true,sortField);
  940. }
  941. // Return an array of the tiddlers that do or do not have a specified entry in the specified storage array (ie, "links" or "tags")
  942. // lookupMatch == true to match tiddlers, false to exclude tiddlers
  943. TiddlyWiki.prototype.reverseLookup = function(lookupField,lookupValue,lookupMatch,sortField)
  944. {
  945. var results = [];
  946. for(var t in this.tiddlers)
  947. {
  948. var tiddler = this.tiddlers[t];
  949. var f = !lookupMatch;
  950. for(var lookup=0; lookup<tiddler[lookupField].length; lookup++)
  951. if(tiddler[lookupField][lookup] == lookupValue)
  952. f = lookupMatch;
  953. if(f)
  954. results.push(tiddler);
  955. }
  956. if(!sortField)
  957. sortField = "title";
  958. results.sort(function (a,b) {if(a[sortField] == b[sortField]) return(0); else return (a[sortField] < b[sortField]) ? -1 : +1; });
  959. return results;
  960. }
  961. // Return the tiddlers as a sorted array
  962. TiddlyWiki.prototype.getTiddlers = function(field)
  963. {
  964. var results = [];
  965. for(var t in this.tiddlers)
  966. results.push(this.tiddlers[t]);
  967. if(field)
  968. results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
  969. return results;
  970. }
  971. // Return array of names of tiddlers that are referred to but not defined
  972. TiddlyWiki.prototype.getMissingLinks = function(sortField)
  973. {
  974. var results = [];
  975. for(var t in this.tiddlers)
  976. {
  977. var tiddler = this.tiddlers[t];
  978. for(var n=0; n<tiddler.links.length;n++)
  979. {
  980. var link = tiddler.links[n];
  981. if(this.tiddlers[link] == null)
  982. results.pushUnique(link);
  983. }
  984. }
  985. results.sort();
  986. return results;
  987. }
  988. // Return an array of names of tiddlers that are defined but not referred to
  989. TiddlyWiki.prototype.getOrphans = function()
  990. {
  991. var results = [];
  992. for(var t in this.tiddlers)
  993. if(this.getReferringTiddlers(t).length == 0)
  994. results.push(t);
  995. results.sort();
  996. return results;
  997. }
  998. // ---------------------------------------------------------------------------------
  999. // Tiddler functions
  1000. // ---------------------------------------------------------------------------------
  1001. // Display several tiddlers from a list of space separated titles
  1002. function displayTiddlers(src,titles,state,highlightText,highlightCaseSensitive,animate,slowly)
  1003. {
  1004. var tiddlerNames = titles.readBracketedList();
  1005. for(var t = tiddlerNames.length-1;t>=0;t--)
  1006. displayTiddler(src,tiddlerNames[t],state,highlightText,highlightCaseSensitive,animate,slowly);
  1007. }
  1008. // Display a tiddler with animation and scrolling, as though a link to it has been clicked on
  1009. // src = source element object (eg link) for animation effects and positioning
  1010. // title = title of tiddler to display
  1011. // state = 0 is default or current state, 1 is read only and 2 is edittable
  1012. // highlightText = text to highlight in the displayed tiddler
  1013. // highlightCaseSensitive = flag for whether the highlight text is case sensitive
  1014. function displayTiddler(src,title,state,highlightText,highlightCaseSensitive,animate,slowly)
  1015. {
  1016. var place = document.getElementById("tiddlerDisplay");
  1017. var after = findContainingTiddler(src); // Which tiddler this one will be positioned after
  1018. var before;
  1019. if(after == null)
  1020. before = place.firstChild;
  1021. else if(after.nextSibling)
  1022. before = after.nextSibling;
  1023. else
  1024. before = null;
  1025. var theTiddler = createTiddler(place,before,title,state,highlightText,highlightCaseSensitive);
  1026. if(src)
  1027. {
  1028. if(config.options.chkAnimate && (animate == undefined || animate == true))
  1029. anim.startAnimating(new Zoomer(title,src,theTiddler,slowly),new Scroller(theTiddler,slowly));
  1030. else
  1031. window.scrollTo(0,ensureVisible(theTiddler));
  1032. }
  1033. }
  1034. // Create a tiddler if it doesn't exist (with no fancy animating)
  1035. // place = parent element
  1036. // before = node before which to create/move the tiddler
  1037. // title = title of tiddler to display
  1038. // state = 0 is default or current state, 1 is read only and 2 is edittable
  1039. // highlightText = text to highlight in the displayed tiddler
  1040. // highlightCaseSensitive = flag for whether the highlight text is case sensitive
  1041. function createTiddler(place,before,title,state,highlightText,highlightCaseSensitive)
  1042. {
  1043. var theTiddler = createTiddlerSkeleton(place,before,title);
  1044. createTiddlerTitle(title,highlightText,highlightCaseSensitive);
  1045. var theViewer = document.getElementById("viewer" + title);
  1046. var theEditor = document.getElementById("editorWrapper" + title);
  1047. switch(state)
  1048. {
  1049. case 0:
  1050. if(!theViewer && !theEditor)
  1051. {
  1052. createTiddlerToolbar(title,false);
  1053. createTiddlerViewer(title,highlightText,highlightCaseSensitive);
  1054. createTiddlerFooter(title,false);
  1055. }
  1056. break;
  1057. case 1: // Viewer
  1058. if(theViewer)
  1059. theViewer.parentNode.removeChild(theViewer);
  1060. if(theEditor)
  1061. theEditor.parentNode.removeChild(theEditor);
  1062. createTiddlerToolbar(title,false);
  1063. createTiddlerViewer(title,highlightText,highlightCaseSensitive);
  1064. createTiddlerFooter(title,false);
  1065. break;
  1066. case 2: // Editor
  1067. if(!theEditor)
  1068. {
  1069. if(theViewer)
  1070. theViewer.parentNode.removeChild(theViewer);
  1071. createTiddlerToolbar(title,true);
  1072. createTiddlerEditor(title);
  1073. createTiddlerFooter(title,true);
  1074. }
  1075. break;
  1076. }
  1077. return(theTiddler);
  1078. }
  1079. function refreshTiddler(title)
  1080. {
  1081. var theViewer = document.getElementById("viewer" + title);
  1082. if(theViewer)
  1083. {
  1084. theViewer.parentNode.removeChild(theViewer);
  1085. createTiddlerViewer(title,null,null);
  1086. }
  1087. }
  1088. function createTiddlerSkeleton(place,before,title)
  1089. {
  1090. var theTiddler = document.getElementById("tiddler" + title);
  1091. if(!theTiddler)
  1092. {
  1093. theTiddler = createTiddlyElement(null,"div","tiddler" + title,"tiddler",null);
  1094. theTiddler.onmouseover = onMouseOverTiddler;
  1095. theTiddler.onmouseout = onMouseOutTiddler;
  1096. theTiddler.ondblclick = onDblClickTiddler;
  1097. var theInnerTiddler = createTiddlyElement(theTiddler,"div",null,"unselectedTiddler",null);
  1098. var theToolbar = createTiddlyElement(theInnerTiddler,"div","toolbar" + title,"toolbar", null);
  1099. var theTitle = createTiddlyElement(theInnerTiddler,"div","title" + title,"title",null);
  1100. var theBody = createTiddlyElement(theInnerTiddler,"div","body" + title,"body",null);
  1101. var theFooter = createTiddlyElement(theInnerTiddler,"div","footer" + title,"footer",null);
  1102. place.insertBefore(theTiddler,before);
  1103. }
  1104. return(theTiddler);
  1105. }
  1106. function createTiddlerTitle(title,highlightText,highlightCaseSensitive)
  1107. {
  1108. var theTitle = document.getElementById("title" + title);
  1109. if(theTitle)
  1110. {
  1111. removeChildren(theTitle);
  1112. if(highlightText == "")
  1113. highlightText = null;
  1114. var highlightRegExp,highlightMatch;
  1115. if(highlightText)
  1116. {
  1117. highlightRegExp = new RegExp(highlightText,highlightCaseSensitive ? "mg" : "img");
  1118. highlightMatch = highlightRegExp.exec(title);
  1119. }
  1120. highlightMatch = subWikify(theTitle,title,0,title.length,highlightRegExp,highlightMatch);
  1121. var tiddler = store.tiddlers[title];
  1122. if(tiddler)
  1123. theTitle.title = tiddler.getSubtitle();
  1124. }
  1125. }
  1126. // Create a tiddler toolbar according to whether it's an editor or not
  1127. function createTiddlerToolbar(title,isEditor)
  1128. {
  1129. var theToolbar = document.getElementById("toolbar" + title);
  1130. var lingo = config.views;
  1131. if(theToolbar)
  1132. {
  1133. removeChildren(theToolbar);
  1134. insertSpacer(theToolbar);
  1135. if(isEditor)
  1136. {
  1137. // Editor toolbar
  1138. lingo = lingo.editor;
  1139. createTiddlyButton(theToolbar,lingo.toolbarDone.text,lingo.toolbarDone.tooltip,onClickToolbarSave);
  1140. insertSpacer(theToolbar);
  1141. createTiddlyButton(theToolbar,lingo.toolbarCancel.text,lingo.toolbarCancel.tooltip,onClickToolbarUndo);
  1142. insertSpacer(theToolbar);
  1143. createTiddlyButton(theToolbar,lingo.toolbarDelete.text,lingo.toolbarDelete.tooltip,onClickToolbarDelete);
  1144. }
  1145. else
  1146. {
  1147. // Viewer toolbar
  1148. lingo = lingo.wikified;
  1149. createTiddlyButton(theToolbar,lingo.toolbarClose.text,lingo.toolbarClose.tooltip,onClickToolbarClose);
  1150. insertSpacer(theToolbar);
  1151. if(!readOnly)
  1152. {
  1153. createTiddlyButton(theToolbar,lingo.toolbarEdit.text,lingo.toolbarEdit.tooltip,onClickToolbarEdit);
  1154. insertSpacer(theToolbar);
  1155. }
  1156. createTiddlyButton(theToolbar,lingo.toolbarPermalink.text,lingo.toolbarPermalink.tooltip,onClickToolbarPermaLink);
  1157. insertSpacer(theToolbar);
  1158. createTiddlyButton(theToolbar,lingo.toolbarReferences.text,lingo.toolbarReferences.tooltip,onClickToolbarReferences);
  1159. }
  1160. insertSpacer(theToolbar);
  1161. }
  1162. }
  1163. function createTiddlerPopup(srcElement)
  1164. {
  1165. var popup = document.getElementById("popup");
  1166. if(popup && popup.nextSibling == srcElement)
  1167. {
  1168. hideTiddlerPopup();
  1169. return null;
  1170. }
  1171. if(popup)
  1172. popup.parentNode.removeChild(popup);
  1173. popup = createTiddlyElement(null,"div","popup",null,null);
  1174. var leftPx = srcElement.offsetLeft;
  1175. var topPx = srcElement.offsetTop;
  1176. var heightPx = srcElement.offsetHeight;
  1177. if (leftPx <= 1 && srcElement.parentNode.offsetLeft > 0)
  1178. leftPx = srcElement.parentNode.offsetLeft;
  1179. if (topPx <= 1 && srcElement.parentNode.offsetTop > 0)
  1180. topPx = srcElement.parentNode.offsetTop;
  1181. if (heightPx <= 1 && srcElement.parentNode.offsetHeight > 0)
  1182. heightPx = srcElement.parentNode.offsetHeight;
  1183. popup.style.left = leftPx + "px";
  1184. popup.style.top = topPx + heightPx + "px";
  1185. popup.style.display = "block";
  1186. srcElement.onmouseout = onMouseOutTiddlerPopup;
  1187. srcElement.appendChild(popup);
  1188. return popup;
  1189. }
  1190. function scrollToTiddlerPopup(popup,slowly)
  1191. {
  1192. if(config.options.chkAnimate)
  1193. anim.startAnimating(new Scroller(popup,slowly));
  1194. else
  1195. window.scrollTo(0,ensureVisible(popup));
  1196. }
  1197. function onMouseOutTiddlerPopup(e)
  1198. {
  1199. if (!e) var e = window.event;
  1200. var related = (e.relatedTarget) ? e.relatedTarget : e.toElement;
  1201. try
  1202. {
  1203. while (related != this && related && related.nodeName && related.nodeName.toLowerCase() != "body")
  1204. related = related.parentNode;
  1205. }
  1206. catch(e)
  1207. {
  1208. related = null;
  1209. }
  1210. if(related != this)
  1211. {
  1212. this.onmouseout = null;
  1213. hideTiddlerPopup();
  1214. }
  1215. e.cancelBubble = true;
  1216. if (e.stopPropagation) e.stopPropagation();
  1217. return(false);
  1218. }
  1219. function hideTiddlerPopup()
  1220. {
  1221. var popup = document.getElementById("popup");
  1222. if(popup)
  1223. popup.parentNode.removeChild(popup);
  1224. }
  1225. // Create the body section of a read-only tiddler
  1226. function createTiddlerViewer(title,highlightText,highlightCaseSensitive,htmlElement)
  1227. {
  1228. var theBody = document.getElementById("body" + title);
  1229. if(theBody)
  1230. {
  1231. var tiddler = store.tiddlers[title];
  1232. var tiddlerText = store.getTiddlerText(title);
  1233. var theViewer = createTiddlyElement(theBody,htmlElement ? htmlElement : "div","viewer" + title,"viewer",null);
  1234. if(tiddler)
  1235. theViewer.setAttribute("tags",tiddler.tags.join(" "));
  1236. if(tiddlerText == null)
  1237. {
  1238. tiddlerText = config.views.wikified.defaultText.format([title]);
  1239. theViewer.style.fontStyle = "italic";
  1240. }
  1241. wikify(tiddlerText,theViewer,highlightText,highlightCaseSensitive);
  1242. }
  1243. }
  1244. // Create the footer section of a tiddler
  1245. function createTiddlerFooter(title,isEditor)
  1246. {
  1247. var theFooter = document.getElementById("footer" + title);
  1248. var tiddler = store.tiddlers[title];
  1249. if(theFooter && tiddler)
  1250. {
  1251. removeChildren(theFooter);
  1252. insertSpacer(theFooter);
  1253. if(isEditor)
  1254. {
  1255. }
  1256. else
  1257. {
  1258. var lingo = config.views.wikified.tag;
  1259. var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;
  1260. var theTags = createTiddlyElement(theFooter,"div",null,null,prompt);
  1261. for(var t=0; t<tiddler.tags.length; t++)
  1262. {
  1263. var theTag = createTagButton(theTags,tiddler.tags[t],tiddler.title);
  1264. insertSpacer(theTags);
  1265. }
  1266. }
  1267. }
  1268. }
  1269. // Create a button for a tag with a popup listing all the tiddlers that it tags
  1270. function createTagButton(place,tag,excludeTiddler)
  1271. {
  1272. var theTag = createTiddlyButton(place,tag,config.views.wikified.tag.tooltip.format([tag]),onClickTag);
  1273. theTag.setAttribute("tag",tag);
  1274. if(excludeTiddler)
  1275. theTag.setAttribute("tiddler",excludeTiddler);
  1276. return(theTag);
  1277. }
  1278. // Create the body section of an edittable tiddler
  1279. function createTiddlerEditor(title)
  1280. {
  1281. var theBody = document.getElementById("body" + title);
  1282. if(theBody)
  1283. {
  1284. var tiddlerText = store.getTiddlerText(title);
  1285. var tiddlerExists = (tiddlerText != null);
  1286. if(!tiddlerExists)
  1287. tiddlerText = config.views.editor.defaultText.format([title]);
  1288. var theEditor = createTiddlyElement(theBody,"div","editorWrapper" + title,"editor",null);
  1289. theEditor.onkeypress = onEditKey;
  1290. var theTitleBox = createTiddlyElement(theEditor,"input","editorTitle" + title,null,null);
  1291. theTitleBox.setAttribute("type","text");
  1292. theTitleBox.value = title;
  1293. theTitleBox.setAttribute("size","40");
  1294. var theBodyBox = createTiddlyElement(theEditor,"textarea","editorBody" + title,null,null);
  1295. theBodyBox.value = tiddlerText;
  1296. var rows = 10;
  1297. var lines = tiddlerText.match(regexpNewLine);
  1298. if(lines != null && lines.length > rows)
  1299. rows = lines.length + 5;
  1300. theBodyBox.setAttribute("rows",rows);
  1301. var theTagsBox = createTiddlyElement(theEditor,"input","editorTags" + title,null,null);
  1302. theTagsBox.setAttribute("type","text");
  1303. var tiddler = store.tiddlers[title];
  1304. theTagsBox.value = tiddler ? tiddler.getTags() : "";
  1305. theTagsBox.setAttribute("size","40");
  1306. var tagPrompt = createTiddlyElement(theEditor,"div",null,"editorFooter",config.views.editor.tagPrompt);
  1307. insertSpacer(tagPrompt);
  1308. var lingo = config.views.editor.tagChooser;
  1309. var addTag = createTiddlyButton(tagPrompt,lingo.text,lingo.tooltip,onClickAddTag);
  1310. addTag.setAttribute("tiddler",title);
  1311. theBodyBox.focus();
  1312. }
  1313. }
  1314. function saveTiddler(title)
  1315. {
  1316. var titleBox = document.getElementById("editorTitle" + title);
  1317. var newTitle = titleBox.value;
  1318. if(store.tiddlers[newTitle])
  1319. {
  1320. if(newTitle != title && !confirm(config.messages.overwriteWarning.format([newTitle.toString()])))
  1321. {
  1322. titleBox.focus();
  1323. titleBox.select();
  1324. return;
  1325. }
  1326. }
  1327. var body = document.getElementById("editorBody" + title);
  1328. var newBody = body.value;
  1329. var newTags = document.getElementById("editorTags" + title).value;
  1330. blurTiddler(title);
  1331. store.saveTiddler(title,newTitle,newBody.replace(regexpCarriageReturn,""),config.options.txtUserName,new Date(),newTags);
  1332. displayTiddler(null,newTitle,1,null,null,null,false,false);
  1333. // Close the old tiddler if this is a rename
  1334. if(title != newTitle)
  1335. {
  1336. var oldTiddler = document.getElementById("tiddler" + title);
  1337. var newTiddler = document.getElementById("tiddler" + newTitle);
  1338. oldTiddler.parentNode.replaceChild(newTiddler,oldTiddler);
  1339. }
  1340. if(config.options.chkAutoSave)
  1341. saveChanges();
  1342. }
  1343. function selectTiddler(title)
  1344. {
  1345. var e = document.getElementById("tiddler" + title);
  1346. if(e != null)
  1347. e.firstChild.className = "selectedTiddler";
  1348. }
  1349. function deselectTiddler(title)
  1350. {
  1351. var e = document.getElementById("tiddler" + title);
  1352. if(e != null)
  1353. e.firstChild.className = "unselectedTiddler";
  1354. }
  1355. function blurTiddler(title)
  1356. {
  1357. var body = document.getElementById("editorBody" + title);
  1358. if(title)
  1359. {
  1360. body.focus();
  1361. body.blur();
  1362. }
  1363. }
  1364. function deleteTiddler(title)
  1365. {
  1366. closeTiddler(title,false);
  1367. store.removeTiddler(title);
  1368. // Autosave
  1369. if(config.options.chkAutoSave)
  1370. saveChanges();
  1371. }
  1372. function closeTiddler(title,slowly)
  1373. {
  1374. var tiddler = document.getElementById("tiddler" + title);
  1375. if(tiddler != null)
  1376. {
  1377. scrubIds(tiddler);
  1378. if(config.options.chkAnimate)
  1379. anim.startAnimating(new Slider(tiddler,false,slowly,"all"));
  1380. else
  1381. tiddler.parentNode.removeChild(tiddler);
  1382. }
  1383. }
  1384. function scrubIds(e)
  1385. {
  1386. if(e.id)
  1387. e.id = null;
  1388. var children = e.childNodes;
  1389. for(var t=0; t<children.length; t++)
  1390. {
  1391. var c = children[t];
  1392. if(c.id)
  1393. c.id = null;
  1394. }
  1395. }
  1396. function closeAllTiddlers()
  1397. {
  1398. clearMessage();
  1399. var place = document.getElementById("tiddlerDisplay");
  1400. var tiddler = place.firstChild;
  1401. var nextTiddler;
  1402. while(tiddler)
  1403. {
  1404. nextTiddler = tiddler.nextSibling;
  1405. if(tiddler.id)
  1406. if(tiddler.id.substr(0,7) == "tiddler")
  1407. {
  1408. var title = tiddler.id.substr(7);
  1409. if(!document.getElementById("editorWrapper" + title))
  1410. place.removeChild(tiddler);
  1411. }
  1412. tiddler = nextTiddler;
  1413. }
  1414. }
  1415. // ---------------------------------------------------------------------------------
  1416. // Regular expression stuff
  1417. // ---------------------------------------------------------------------------------
  1418. var upperLetter = "[A-Z\u00c0-\u00de\u0150\u0170]";
  1419. var lowerLetter = "[a-z\u00df-\u00ff_0-9\\-\u0151\u0171]";
  1420. var anyLetter = "[A-Za-z\u00c0-\u00de\u00df-\u00ff_0-9\\-\u0150\u0170\u0151\u0171]";
  1421. var anyDigit = "[0-9]";
  1422. var anyNumberChar = "[0-9\\.E]";
  1423. var wikiNamePattern = "(~?)((?:" + upperLetter + "+" + lowerLetter + "+" + upperLetter + anyLetter + "*)|(?:" + upperLetter + "{2,}" + lowerLetter + "+))";
  1424. var urlPattern = "((?:http|https|mailto|ftp):[^\\s'\"]+(?:/|\\b))";
  1425. var explicitLinkPattern = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
  1426. var bracketNamePattern = "\\[\\[([^\\]]+)\\]\\]";
  1427. var wikiNamePatterns;
  1428. var wikiNameRegExp;
  1429. var structurePatterns;
  1430. var stylePatterns;
  1431. var tableRegExp;
  1432. var tableRowColRegExp;
  1433. var invalidPreWikiNamePattern;
  1434. function setupRegexp()
  1435. {
  1436. // Table rows pattern
  1437. var rowPattern = "^\\|([^\\n]*\\|)([fhc]?)$";
  1438. tableRegExp = new RegExp(rowPattern,"mg");
  1439. // Table columns pattern
  1440. var elementPattern = "(?:(?:BGCOLOR|bgcolor)\\(([^\\)]+)\\):)?" +
  1441. "("+
  1442. "("+explicitLinkPattern+")?"+
  1443. "("+bracketNamePattern+")?" +
  1444. "[^\\|]*"+
  1445. ")\\|";
  1446. tableRowColRegExp = new RegExp(elementPattern,"g");
  1447. // Link patterns
  1448. wikiNamePatterns = "(?:" + wikiNamePattern +
  1449. ")|(?:" + urlPattern +
  1450. ")|(?:" + explicitLinkPattern +
  1451. ")|(?:" + bracketNa

Large files files are truncated, but you can click here to view the full file