Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
{{firstletter{
@@color:#930;B@@
}}}aseDocumenter proposes, beside the use of usual menus to run the usual functions implemented by the software, also an ''API (Application Programming Interface)''.
The macros described below can be called from any user macro to execute several tasks that the user wants to automate, for whatever reason: housekeeping, repetitive execution, launch from toolbar button, multiple repositories, templates modifications, ...
!!Preliminary remarks
*The ~BaseDocumenter macro library should be preloaded beforehand, typically in the invoked user macro itself.
*Most functions require the previous opening of the [[reporitory|Repository]]. Closing it at the end is also a good programming practice.
!!Implemented functions
| !Function | !Function Description | !Argument(s) | !Optional | !Type | !Default value | !Argument(s) Description |
|''~BD_OpenRepository'' |Open the repository. It will remain open until it is closed explicitly. |Repository | Y | String | "~BaseDocumenter" |Registered name or complete filepath. |
|~|~|User | Y | String | | |
|~|~|Password | Y | String | | |
|''~BD_CloseRepository'' |Close the actually open repository, |Compact | Y | Boolean | False |If True, execute "CHECKPOINT DEFRAG" SQL statement before closing. |
|''~BD_CreateRepository'' |Create a new repository, |Filename | N | String | |Complete filepath.<br />Use either the URL or the ~OS-specific (e.g. C:\...) syntax. |
|~|~|Register | Y | Boolean | True | |
|~|~|Registername | Y | String | "~BaseDocumenter" | |
|''~BD_SetOptions'' |Open the Preferences dialog box to define or update the general options/preferences. | | | | | |
|''~BD_ScanThisDatabase'' |Launch scanning phase of the currently active database file.<br />To generate the documentation, use //~BD_DocumentDatabase//. | | | | | |
|''~BD_ScanAndDocThisDatabase'' |Launch both scanning and documentation generation phases of the currently active database file. | | | | | |
|''~BD_DocumentDatabase'' |Launch documentation generation phase of the concerned database file.<br />The database file is presumed already scanned. |Database | Y | String | Empty string |Database short name.<br />If empty string, (re)document all databases present in the repository. |
|''~BD_ForgetDatabase'' |Erase completely the mentioned database from the repository.<br />Eventual previously generated HTML pages are not erased. |Database | N | String | |Database short name. |
|''~BD_WithUI'' |Execute next commands with or without user interface. |Option | Y | Boolean | True |If False, no user interface. |
All functions return a boolean {{{True}}} value if the call was successful.
!!Example
//{{{
REM Remake the documentation of all databases present in the repository
Sub Redoc()
Dim oLibraries As Object
Set oLibraries = GlobalScope.BasicLibraries
If Not oLibraries.isLibraryLoaded("BaseDocumenter") Then oLibraries.loadLibrary("BaseDocumenter")
' No user interface
BD_WithUI(False)
' Open the repository
BD_OpenRepository("myRegisteredRepo")
' Re-document all databases, e.g. because the output template file has been modified
BD_DocumentDatabase()
' Close the repository
BD_CloseRepository()
End Sub
//}}}
<script>
if (!window.story) window.story=window;
var url="http://www.access2base.com/basedocumenter/basedocumenter.html"; //store.getTiddlerText("SiteUrl");
if (!url) url=document.location.href;
var title=story.findContainingTiddler(place).id.substr(7).replace('_',' '); //var title=story.findContainingTiddler(place).id.substr(7)
var permalink=encodeURIComponent(String.encodeTiddlyLink(title));
return "\n"+"|Bookmark this page » » [["+title+"|"+url+"#"+permalink+"]]|";
</script>
{{firstletter{
@@color:#930;T@@
}}}o maximize the exposure of the ''~BaseDocumenter'' software to a broad range of contexts, examples of database files have been gathered from several sources found on the web (forums, tutorials, ...) and submitted to a documentation process.
__The results are visitable from the ''[[EXAMPLES SITE|http://www.access2base.com/basedocumenter/examples/TOC.html]]''__.
!!!Typical examples include ...
| !Scope | !Comments |
|(Very ?) complex Basic libraries |The whole ''~Access2Base'' library (> 20,000 lines). |
|~|A very nice set of "''Basic primitives''" found [[HERE|https://wiki.documentfoundation.org/Macros/Basic_Primitives]] (~10,000 lines). |
|~|The well-known ''[[XRayTools|http://berma.pagesperso-orange.fr/index2.html]]'' library from Bernard Marcelly. |
|Very complete Base applications|The ''~GenoBase'' application developed and kindly proposed by Gisbert Friege.<br />Read more [[HERE|http://genobase.friege.de/]]. |
|~|A database for managing a football/soccer ''~WorldCup'', made by Villeroy.<br/>A.o. you will find there a form with 166 controls located in up to 3 levels of nested subforms.<br />Read more [[HERE|https://forum.openoffice.org/en/forum/viewtopic.php?f=100&t=70259]]. |
|Tutorials |A set of sample databases created to accompany the "''Base Handbook''".<br />You can find them [[HERE|https://wiki.documentfoundation.org/images/5/52/Sample-databases.zip]]. |
|~|The ''~NorthWind'' database which the ~Access2Base tutorial is based on. |
|>| Visit the ''[[EXAMPLES SITE|http://www.access2base.com/basedocumenter/examples/TOC.html]]'' |
!!!Templates
I'm definitely __NOT a web designer__ and the given examples should only serve as inspiration for what could be produced with the proposed techniques. Not more, not less.
To view or download the 2 used [[templates|Templates]], 1 for the table of contents and 1 for the documentation pages, the simplest is to open either
*the [[TOC template|http://www.access2base.com/basedocumenter/examples/BD_TOC_Template.html]]
*or the [[template for documentation pages|http://www.access2base.com/basedocumenter/examples/BD_Template.html]]
and to view their page source.
Both use next [[CSS stylesheet|http://www.access2base.com/basedocumenter/examples/BD_Stylesheet.css]]:
//{{{
<link rel="stylesheet" type="text/css" href="./BD_Stylesheet.css">
//}}}
Additionally a few javascripts, based on jquery, enhance the behaviour of the pages:
*by forcing the data table header to stay on the top of the page, even when the page is scrolled down;
*by displaying the vertical table of contents like a clickable tree.
Thanks to the authors of those smart pieces of code: see [[http://mkoryak.github.io/floatThead/|http://mkoryak.github.io/floatThead/]] and [[http://www.dynamicdrive.com/dynamicindex1/treeview/index.htm|http://www.dynamicdrive.com/dynamicindex1/treeview/index.htm]].
//{{{
<link rel="stylesheet" type="text/css" href="../jquery/jquery.treeview.css">
<script type="text/javascript" src="../jquery/jquery-1.8.0.min.js"></script>
<script type="text/javascript" src="../jquery/jquery.floatThead.min.js"></script>
<script type="text/javascript" src="../jquery/jquery.treeview.min.js"></script>
//}}}
!What is ''__~BaseDocumenter__'' ?
{{firstletter{
@@color:#930;B@@
}}}''aseDocumenter'' is a software tool producing a ''__full documentation__'' of a ''~LibreOffice Base application''.
Such an application includes
*a //back-end// part, i.e. the database with its tables, views and fields
*a //front-end// part, i.e. the user interface with its SQL queries, forms, dialogs, buttons, scripts, etc.
The front-end is contained in one single file, called here the ''database file''. Its name has usually "''.odb''" as suffix. The back-end can be either embedded in the same //database file// or located on a separate //database server//.
!How does the generated documentation look like ?
The documentation produced by ''~BaseDocumenter'' is bundled as one set of ''static HTML pages''. Each //database file// is documented in its own single directory.
The layout of the produced HTML pages is highly ''customizable''.
The documentation is thus best read thru a ''web browser''.
The documentation ''describes'' in detail all the items being part of the Base application.
Additionally it identifies all the ''dependencies'' between items. E.g. a //query// might use one or more //tables//. Knowing exhaustively which items are used by other items is invaluable for the developer of the application. This knowledge allows for example a detailed ''impact analysis'' of design changes.
Dependencies are of 2 types:
*''parent/child'': e.g. a //field// is the child of a //table//.
*''uses/used by'': e.g. a //query// uses a //table// or a //table// is used by a //query//. In //~BaseDocumenter//, such dependencies are very simply revealed by the use of ''__hyperlinks__''. Clicking on one of them makes the browser jump to the description of the linked item.
The software includes also
*a ''Basic parser'' to identify a.o. which procedures are called by which ones
*a ''SQL beautifier'' to make simple or complex SQL statements much more readable
!The kernel of the software
The ~BaseDocumenter software needs to run correctly
*a set of Basic modules
*one Python module
*one //database file//, __created by the user__, called the ~BaseDocumenter ''repository'', which will contain:
**every item found in the documented database files
**every identified dependency between those items
!To know more ...
... read next pages
*[[Getting started|Install]]
*The [[documentation process|Process]]
*The [[repository|Repository]]
/***
|Name|InlineJavascriptPlugin|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|Insert Javascript executable code directly into your tiddler content.|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Documentation
>see [[InlineJavascriptPluginInfo]]
!!!!!Revisions
<<<
2010.12.15 1.9.6 allow (but ignore) type="..." syntax
|please see [[InlineJavascriptPluginInfo]] for additional revision details|
2005.11.08 1.0.0 initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 6, date: new Date(2010,12,15)};
config.formatters.push( {
name: "inlineJavascript",
match: "\\<script",
lookahead: "\\<script(?: type=\\\"[^\\\"]*\\\")?(?: src=\\\"([^\\\"]*)\\\")?(?: label=\\\"([^\\\"]*)\\\")?(?: title=\\\"([^\\\"]*)\\\")?(?: key=\\\"([^\\\"]*)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",
handler: function(w) {
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var src=lookaheadMatch[1];
var label=lookaheadMatch[2];
var tip=lookaheadMatch[3];
var key=lookaheadMatch[4];
var show=lookaheadMatch[5];
var code=lookaheadMatch[6];
if (src) { // external script library
var script = document.createElement("script"); script.src = src;
document.body.appendChild(script); document.body.removeChild(script);
}
if (code) { // inline code
if (show) // display source in tiddler
wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
if (label) { // create 'onclick' command link
var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
link.tiddler=w.tiddler;
link.onclick=function(){
this.bufferedHTML="";
try{ var r=eval(this.code);
if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
if(this.bufferedHTML.length)
s.innerHTML=this.bufferedHTML;
if((typeof(r)==="string")&&r.length) {
wikify(r,s,null,this.tiddler);
return false;
} else return r!==undefined?r:false;
} catch(e){alert(e.description||e.toString());return false;}
};
link.setAttribute("title",tip||"");
var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
link.setAttribute("href",URIcode);
link.style.cursor="pointer";
if (key) link.accessKey=key.substr(0,1); // single character only
}
else { // run script immediately
var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
try { var out=eval(c); }
catch(e) { out=e.description?e.description:e.toString(); }
if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
}
}
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
}
} )
//}}}
// // Backward-compatibility for TW2.1.x and earlier
//{{{
if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
if(limit > 0) text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
}
//}}}
// // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
//{{{
if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
//}}}
/***
|Name|InlineJavascriptPluginInfo|
|Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
|Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
|Version|1.9.6|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|documentation|
|Description|Documentation for InlineJavascriptPlugin|
''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated ~TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
!!!!!Usage
<<<
This plugin adds wiki syntax for surrounding tiddler content with {{{<script>}}} and {{{</script>}}} markers, so that it can be recognized as embedded javascript code. When a tiddler is rendered, the plugin automatically invokes any embedded scripts, which can be used to construct and return dynamically-generated output that is inserted into the tiddler content.
{{{
<script type="..." src="..." label="..." title="..." key="..." show>
/* javascript code goes here... */
</script>
}}}
All parameters are //optional//. When the ''show'' keyword is used, the plugin will also include the script source code in the output that it displays in the tiddler. This is helpful when creating examples for documentation purposes (such as used in this tiddler!)
__''Deferred execution from an 'onClick' link''__
<script label="click here" title="mouseover tooltip text" key="X" show>
/* javascript code goes here... */
alert('you clicked on the link!');
</script>
By including a {{{label="..."}}} parameter in the initial {{{<script>}}} marker, the plugin will create a link to an 'onclick' script that will only be executed when that specific link is clicked, rather than running the script each time the tiddler is rendered. You may also include a {{{title="..."}}} parameter to specify the 'tooltip' text that will appear whenever the mouse is moved over the onClick link text, and a {{{key="X"}}} parameter to specify an //access key// (which must be a //single// letter or numeric digit only).
__''Loading scripts from external source files''__
<script src="URL" show>
/* optional javascript code goes here... */
</script>You can also load javascript directly from an external source URL, by including a src="..." parameter in the initial {{{<script>}}} marker (e.g., {{{<script src="demo.js"></script>}}}). This is particularly useful when incorporating third-party javascript libraries for use in custom extensions and plugins. The 'foreign' javascript code remains isolated in a separate file that can be easily replaced whenever an updated library file becomes available.
In addition to loading the javascript from the external file, you can also use this feature to invoke javascript code contained within the {{{<script>...</script>}}} markers. This code is invoked //after// the external script file has been processed, and can make immediate use of the functions and/or global variables defined by the external script file.
>Note: To ensure that your javascript functions are always available when needed, you should load the libraries from a tiddler that is rendered as soon as your ~TiddlyWiki document is opened, such as MainMenu. For example: put your {{{<script src="..."></script>}}} syntax into a separate 'library' tiddler (e.g., ~LoadScripts), and then add {{{<<tiddler LoadScripts>>}}} to MainMenu so that the library is loaded before any other tiddlers that rely upon the functions it defines.
>
>Normally, loading external javascript in this way does not produce any direct output, and should not have any impact on the appearance of your MainMenu. However, if your ~LoadScripts tiddler contains notes or other visible content, you can suppress this output by using 'inline CSS' in the MainMenu, like this: {{{@@display:none;<<tiddler LoadScripts>>@@}}}
<<<
!!!!!Creating dynamic tiddler content and accessing the ~TiddlyWiki DOM
<<<
An important difference between ~TiddlyWiki inline scripting and conventional embedded javascript techniques for web pages is the method used to produce output that is dynamically inserted into the document: in a typical web document, you use the {{{document.write()}}} (or {{{document.writeln()}}}) function to output text sequences (often containing HTML tags) that are then rendered when the entire document is first loaded into the browser window.
However, in a ~TiddlyWiki document, tiddlers (and other DOM elements) are created, deleted, and rendered "on-the-fly", so writing directly to the global 'document' object does not produce the results you want (i.e., replacing the embedded script within the tiddler content), and instead will //completely replace the entire ~TiddlyWiki document in your browser window (which is clearly not a good thing!)//. In order to allow scripts to use {{{document.write()}}}, the plugin automatically converts and buffers all HTML output so it can be safely inserted into your tiddler content, immediately following the script.
''Note that {{{document.write()}}} can only be used to output "pure HTML" syntax. To produce //wiki-formatted// output, your script should instead return a text value containing the desired wiki-syntax content'', which will then be automatically rendered immediately following the script. If returning a text value is not sufficient for your needs, the plugin also provides an automatically-defined variable, 'place', that gives the script code ''direct access to the //containing DOM element//'' into which the tiddler output is being rendered. You can use this variable to ''perform direct DOM manipulations'' that can, for example:
* generate wiki-formatted output using {{{wikify("...content...",place)}}}
* vary the script's actions based upon the DOM element in which it is embedded
* access 'tiddler-relative' DOM information using {{{story.findContainingTiddler(place)}}}
Note:
''When using an 'onclick' script, the 'place' element actually refers to the onclick //link text// itself, instead of the containing DOM element.'' This permits you to directly reference or modify the link text to reflect any 'stateful' conditions that might set by the script. To refer to the containing DOM element from within an 'onclick' script, you can use "place.parentNode" instead.
<<<
!!!!!Instant "bookmarklets"
<<<
You can also use an 'onclick' link to define a "bookmarklet": a small piece of javascript that can be ''invoked directly from the browser without having to be defined within the current document.'' This allows you to create 'stand-alone' commands that can be applied to virtually ANY ~TiddlyWiki document... even remotely-hosted documents that have been written by others!! To create a bookmarklet, simply define an 'onclick' script and then grab the resulting link text and drag-and-drop it onto your browser's toolbar (or right-click and use the 'bookmark this link' command to add it to the browser's menu).
Notes:
*When writing scripts intended for use as bookmarklets, due to the ~URI-encoding required by the browser, ''you cannot not use ANY double-quotes (") within the bookmarklet script code.''
*All comments embedded in the bookmarklet script must ''use the fully-delimited {{{/* ... */}}} comment syntax,'' rather than the shorter {{{//}}} comment syntax.
*Most importantly, because bookmarklets are invoked directly from the browser interface and are not embedded within the ~TiddlyWiki document, there is NO containing 'place' DOM element surrounding the script. As a result, ''you cannot use a bookmarklet to generate dynamic output in your document,'' and using {{{document.write()}}} or returning wiki-syntax text or making reference to the 'place' DOM element will halt the script and report a "Reference Error" when that bookmarklet is invoked.
Please see ~InstantBookmarklets for many examples of 'onclick' scripts that can also be used as bookmarklets.
<<<
!!!!!Special reserved function name
<<<
The plugin 'wraps' all inline javascript code inside a function, {{{_out()}}}, so that any return value you provide can be correctly handled by the plugin and inserted into the tiddler. To avoid unpredictable results (and possibly fatal execution errors), this function should never be redefined or called from ''within'' your script code.
<<<
!!!!!$(...) 'shorthand' function
<<<
As described by Dustin Diaz [[here|http://www.dustindiaz.com/top-ten-javascript/]], the plugin defines a 'shorthand' function that allows you to write:
{{{
$(id)
}}}
in place of the normal standard javascript syntax:
{{{
document.getElementById(id)
}}}
This function is provided merely as a convenience for javascript coders that may be familiar with this abbreviation, in order to allow them to save a few bytes when writing their own inline script code.
<<<
!!!!!Examples
<<<
simple dynamic output:
><script show>
document.write("The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
dynamic output using 'place' to get size information for current tiddler:
><script show>
if (!window.story) window.story=window;
var title=story.findContainingTiddler(place).getAttribute("tiddler");
var size=store.getTiddlerText(title).length;
return title+" is using "+size+" bytes";
</script>
dynamic output from an 'onclick' script, using {{{document.write()}}} and/or {{{return "..."}}}
><script label="click here" show>
document.write("<br>The current date/time is: "+(new Date())+"<br>");
return "link to current user: [["+config.options.txtUserName+"]]\n";
</script>
creating an 'onclick' button/link that accesses the link text AND the containing tiddler:
><script label="click here" title="clicking this link will show an 'alert' box" key="H" show>
if (!window.story) window.story=window;
var txt=place.firstChild.data;
var tid=story.findContainingTiddler(place).getAttribute('tiddler');
alert('Hello World!\nlinktext='+txt+'\ntiddler='+tid);
</script>
dynamically setting onclick link text based on stateful information:
>{{block{
{{{
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.previousSibling.innerHTML=on?"disable":"enable";
</script>
}}}
<script label="click here">
/* toggle "txtSomething" value */
var on=(config.txtSomething=="ON");
place.innerHTML=on?"enable":"disable";
config.txtSomething=on?"OFF":"ON";
return "\nThe current value is: "+config.txtSomething;
</script><script>
/* initialize onclick link text based on current "txtSomething" value */
var on=(config.txtSomething=="ON");
place.lastChild.innerHTML=on?"enable":"disable";
</script>
}}}
loading a script from a source url:
>http://www.TiddlyTools.com/demo.js contains:
>>{{{function inlineJavascriptDemo() { alert('Hello from demo.js!!') } }}}
>>{{{displayMessage('InlineJavascriptPlugin: demo.js has been loaded');}}}
>note: When using this example on your local system, you will need to download the external script file from the above URL and install it into the same directory as your document.
>
><script src="demo.js" show>
return "inlineJavascriptDemo() function has been defined"
</script>
><script label="click to invoke inlineJavascriptDemo()" key="D" show>
inlineJavascriptDemo();
</script>
<<<
!!!!!Revisions
<<<
2010.12.15 1.9.6 allow (but ignore) type="..." syntax
2009.04.11 1.9.5 pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
2009.02.26 1.9.4 in $(), handle leading '#' on ID for compatibility with ~JQuery syntax
2008.06.11 1.9.3 added $(...) function as 'shorthand' for document.getElementById()
2008.03.03 1.9.2 corrected fallback declaration of wikifyPlainText() (fixes Safari "parse error")
2008.02.23 1.9.1 in onclick function, use string instead of array for 'bufferedHTML' (fixes IE errors)
2008.02.21 1.9.0 output from 'onclick' scripts (return value or document.write() calls) are now buffered and rendered into into a span following the script. Also, added default 'return false' handling if no return value provided (prevents HREF from being triggered -- return TRUE to allow HREF to be processed). Thanks to Xavier Verges for suggestion and preliminary code.
2008.02.14 1.8.1 added backward-compatibility for use of wikifyPlainText() in ~TW2.1.3 and earlier
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.28 1.8.0 added support for key="X" syntax to specify custom access key definitions
2007.12.15 1.7.0 autogenerate URI encoded HREF on links for onclick scripts. Drag links to browser toolbar to create bookmarklets. IMPORTANT NOTE: place is NOT defined when scripts are used as bookmarklets. In addition, double-quotes will cause syntax errors. Thanks to ~PaulReiber for debugging and brainstorming.
2007.11.26 1.6.2 when converting "document.write()" function calls in inline code, allow whitespace between "write" and "(" so that "document.write ( foobar )" is properly converted.
2007.11.16 1.6.1 when rendering "onclick scripts", pass label text through wikifyPlainText() to parse any embedded wiki-syntax to enable use of HTML entities or even TW macros to generate dynamic label text.
2007.02.19 1.6.0 added support for title="..." to specify mouseover tooltip when using an onclick (label="...") script
2006.10.16 1.5.2 add newline before closing '}' in 'function out_' wrapper. Fixes error caused when last line of script is a comment.
2006.06.01 1.5.1 when calling wikify() on script return value, pass hightlightRegExp and tiddler params so macros that rely on these values can render properly
2006.04.19 1.5.0 added 'show' parameter to force display of javascript source code in tiddler output
2006.01.05 1.4.0 added support 'onclick' scripts. When label="..." param is present, a button/link is created using the indicated label text, and the script is only executed when the button/link is clicked. 'place' value is set to match the clicked button/link element.
2005.12.13 1.3.1 when catching eval error in IE, e.description contains the error text, instead of e.toString(). Fixed error reporting so IE shows the correct response text. Based on a suggestion by ~UdoBorkowski
2005.11.09 1.3.0 for 'inline' scripts (i.e., not scripts loaded with src="..."), automatically replace calls to 'document.write()' with 'place.innerHTML+=' so script output is directed into tiddler content. Based on a suggestion by ~BradleyMeck
2005.11.08 1.2.0 handle loading of javascript from an external URL via src="..." syntax
2005.11.08 1.1.0 pass 'place' param into scripts to provide direct DOM access
2005.11.08 1.0.0 initial release
<<<
{{firstletter{
@@color:#930;N@@
}}}ext steps are necessary before starting documenting your first database file:
#''Download'' the software.
#Define ''templates''.
#Create the ''repository''.
#Define your initial ''settings''.
!!Install the ~BaseDocumenter extension
!!!Prerequisites
//~BaseDocumenter// uses internally the [[Access2Base|http://www.access2base.com/access2base.html]] library. Its minimal required version is 1.8.0.
As a consequence //~BaseDocumenter// requires a prior installation of at least ''~LibreOffice 6.0''. However, preferably, a prior installation of ''~LibreOffice 6.1'' is recommended.
The software might also work normally with ~OpenOffice and ~Access2Base >= 1.8.0 but this configuration has not been tested and is anyway ''not supported''.
!!!Download //~BaseDocumenter//
... from the ''[[LibreOffice extensions center|https://extensions.libreoffice.org/extensions/basedocumenter-to-document-your-base-applications]]''.
!!!Install the //~BaseDocumenter// extension
The name of the downloaded file is __~BaseDocumenter.oxt__. Select preferably the last proposed version.
Note: //some browsers might download the extension as a .zip file; if this happens rename the downloaded file from .zip to .oxt//.
#Install the extension as any other extension. For more details, follow the instructions in [[Installing an extension (LibO)|https://wiki.documentfoundation.org/Documentation/HowTo/install_extension]] or, alternatively, in [[Installing an extension (AOO)|https://wiki.openoffice.org/wiki/Documentation/Administration_Guide/Using_Package_Manager]].
#When you get next dialog box:<br />[img[Your user or all users|_images/install_extension.png]]<br />then opt for the ''Only for me'' button.
#After the installation, __restart ~LibreOffice__.
!!Define templates
You can read details about templates in the [[Templates]] page.
As a starting point, you can also simply ''DOWNLOAD'' the templates used in the examples from ''[[HERE|http://www.access2base.com/basedocumenter/_download/Templates.zip]]''. Unzip the downloaded file in an empty directory where you plan to store later on the documentation of your databases.
!!Create the repository
~BaseDocumenter will refuse to work without a prior setup of the repository.
The repository is a usual ~LibreOffice __Base file__ containing the usual __ embedded HSQLDB __ database (embedded Firebird is forbidden).
__You can either__:
*__Create the repository manually__, with, typically, the {{{File + New + Database}}} menu item.<br />If you choose to register this new database file, do it, preferably, under the name ''"~BaseDocumenter"''.<br />The software will proceed with the //initialization// of the repository when you open it for the first time.
*__Or (easier)__ ...
**Open any existing Base document in your environment ''__without macros enabled__''
**Select the {{{BaseDocumenter + New repository}}}.<br />[img[Create repository confirmation message|_images/create_repository.png]]<br />Confirm to continue, select a directory and a file name with the proposed file picker.<br />The repository will be created and __initialized__.
After initialization, the repository will contain 2 tables: {{{DATABASES}}} and {{{OBJECTS}}}.
It is strictly forbidden to alter those tables manually or to add extra tables. However adding queries or other design elements is fair.
To know more ... [[about how the repositoryv is structured|Repository]].
!!Set your default preferences
When opening any //.odb// database file, a new menu, {{{BaseDocumenter}}} will appear.
#If your repository has not been registered under the name //~BaseDocumenter//, then select and execute the {{{BaseDocumenter + Open repository}}} menu item.
#Select the {{{BaseDocumenter + Preferences ...}}} menu item.<br />[img[Default preferences|_images/preferences_gen.png]]
#The minimal required setup at this stage is to define __the place where the resulting documentation will be stored__, i.e. the ''HTML output pages directory''. If you have installed the proposed templates, give there the directory where you unzipped them.
#For ''Template file for table of contents'' and ''Template for HTML output pages'', refer to respectively the __~BD_TOC_Template.html__ and __~BD_Template.html__ files.
Read more about the setup of your [[preferences|Preferences]] ...
!!Document your databases
To know how to produce a documentation for your own databases, read the [[process|Process]] page.
!!Limitations of the current release of ~BaseDocumenter
!!!RDBMS
~BaseDocumenter is a quite complex software. Obviously most tests have been done with HSQLDB (both 1.8 and 2.x versions) as targeted database.
Some tests have been done with ~MSAccess (2003 and 2007 formats), ~SqLite and Postgres. With success.
But ...
*The availability of the 3.0 version being very recent, at this moment of time the software does not accept Firebird as back-end.
!!!Non documented items
Next items could also advantageously be documented but are not present in the actual release:
*Reports
*Dependencies between fields and controls
!!!Known errors
*Hierarchical form names might cause a scanning error.
*Forms may have more than 1 data source. This feature is seldom used in practice. However multiple data sources are identified only if ~BaseDocumenter is installed near __~LibreOffice 6.1__ or later release.
[[Software Version: 0.6.0|ReleaseNotes]]
<<search>>
[[Home|Home]]
[[Getting started|Install]]
[[The process|Process]]
[[Relations]]
[[Repository structure|Repository]]
[[Templating|Templates]]
[[CSS styles|Styling]]
[[Preferences]]
[[API]]
[[Limitations]]
''[[Examples]]''
[[Thanks|Thanks]]
[[Contact]]
<<toggleSideBar "" "Toggle side bar" hide>>
<!--{{{-->
<div class='header'>
<div class='titleLine'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div macro='gradient vert #ffffff #cc9900'><a> </a><div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
</div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
{{firstletter{
@@color:#930;B@@
}}}efore using //~BaseDocumenter// it is mandatory to go at least once thru setting your ''general options''.
As a minimum, the software will not run as long as the user has not defined the __output directory__ where the produced documentation should be stored.
The majority of the other options/preferences let you define the __scope of the scanning__ phase. Which items and which dependencies should be explored and documented ?
~BaseDocumenter uses indeed a lot of resources. Being selective can improve the processing time.
Options can be set at 2 levels:
*__(General) options__: options set globally for all the database files that have never been scanned. The general options are preserved until they are changed.<br />Define them from the ''{{{BaseDocumenter + Options ...}}}'' menu item.
*__(Specific) preferences__: preferences set for one single database. These preferences are preserved until the user changes them again and are reused each time a newer version of the concerned database file is scanned again.<br />Setting those preferenvces is done by pressing the ''{{{Preferences}}}'' button in the main ~BaseDocumenter dialog window.
!!Database
[img[Database|_images/preferences_01.png]]
*This page appears only for __specific preferences__.
*The database short name determines also the name of the ''subdirectory'' in which the documentation will be stored.
*The free text will be displayed in the ''database.html'' page related to the concerned database.
!!Files & Directories
[img[Database|_images/preferences_02.png]]
*The template files are described in the [[templates|Templates]] page.
*The TOC template file and the HTML output directory controls are modifiable only when __general options__ are defined.
*The template file for the documentation itself can be defined at general and specific levels.
!!Tables & Queries
[img[Database|_images/preferences_03.png]]
*Collecting data samples and data statistics means that some data contained in the database tables will be displayed in the documentation. __This is not always desirable for privacy reasons__.
*Additionally collecting data statistics could be costly for large tables. Note that this operation is executed __by the RDBMS __ with __one single SQL statement__ per table.
*Parsing and beautifying SQL is a very nice feature, but also costly in processing power. Note that this option parses not only queries but also any SQL present in forms, views or (listbox ...) controls.
!!Forms & Dialogs
[img[Database|_images/preferences_04.png]]
*Form and dialog ''screenshots'' have to be made by the user and stored in the indicated subdirectories and named following the given template. The documentation will provide the __correct URL __ to allow the web browser to load them.
*You can opt to document also the dialogs present in ''//preloaded// libraries''. A library can be preloaded only if the database was opened __with the macro's enabled__. This is not the recommended way of using ~BaseDocumenter. So, know what you're doing.
!!Modules & Procedures
[img[Database|_images/preferences_05.png]]
*Parsing the Basic modules is a very nice feature, but alse VERY costly in processing power.
*You can opt to document also the modules present in ''//preloaded// libraries''. A library can be preloaded only if the database was opened __with the macro's enabled__. This is not the recommended way of using ~BaseDocumenter. So, know what you're doing.
{{firstletter{
@@color:#930;T@@
}}}o produce the documentation of a database file, ~BaseDocumenter goes thru ''2 major steps''.
#The __scanning__ step.
#The __documentation generation__ step.
They can be either
*executed completely separately from each other (even if the first step should obviously precede the second one).
*chained and executed one immediately after the other. This is the default behaviour of ~BaseDocumenter if you use the proposed menu items.
The reason of this duality is the following: the generated documentation consists in the current release of ~BaseDocumenter in a set of static HTML pages. A future release could, maybe, also allow alternative formats for the documentation, e.g.an odt/pdf file or a dynamic dialog with a treeview describing the relations between items. Anyway such a documentation will still be produced from the results of the //scanning// phase.
!!Open the repository
Whatever the step, the [[repository|Repository]] must be opened beforehand. It can be opened for one single user only at the same time.
Either
*Use the {{{BaseDocumenter + Open repository}}} menu item to open the repository __manually__. If the software does not find a registered database named //~BaseDocumenter//, a file picker will let you designate the relevant Base file.
*Or let the software open the repository automatically : ~BaseDocumenter will open the database file registered under the name //~BaseDocumenter//.
If the file is found without any table, it will be initialized. If the file contains exactly 2 tables with resp. DATABASES and OBJECTS as names, it will get opened normally. Otherwise the file will not be recognized as a ~BaseDocumenter repository and its opening will fail.
!!Schema of the process
[img[The BaseDocumenter process|_images/process.png]]
!!Setting //default// options
Use the {{{BaseDocumenter + Options ...}}} menu item to define your __default__ options, i.e. those you want to be applied when documenting database files __for the first time__.
More details to be found in the [[options/preferences|Preferences]] page.
!!~STEP1: the scanning
#Open ~LibreOffice
#Open the database file (.odb) that you want ~BaseDocumenter to scan, __''without enabling the execution of macros''__.<br />This will prevent any interference of form or dialog events during the scanning step.<br />Preferably, do not open any other ~LibreOffice document at the same time.
#Open the repository, implicitly or manually, as described above
#Activate the {{{BaseDocumenter + Document this database}}} menu item.
#A dialog will appear with 3 buttons:
##Click on ''START'' to launch the scan.
##Click on ''Cancel'' to not scan anything.
##Click on ''Preferences ...'' to define your ''//specific// preferences'', i.e. the preferences that you want to be applied on the current database file.<br />The chosen preferences will be applied to any re-documentation of the database until you change them again.
##During the scan its progress is displayed continuously in the central text box.<br />Forms scanning requires them to be opened. They will appear briefly. The opening mode is //Edit// to avoid any data access.<br />Once started the scan can be interrupted at any moment with the ''STOP'' button.
Results of the scanning;
*The //repository// is loaded with all the data collected during the scanning.<br />The documented database file however is __left unchanged__.
*The status of the scanning is set to DONE in the repository.
*The log of the scanning is stored in the SCANLOG field of the relevant DATABASES record.
!!~STEP2: Documentation generation
#If the scan has been launched with the {{{BaseDocumenter + Document this database}}} menu item, the documentation generation will start automatically after the scanning.<br />However there are alternative modes that allow to run the documentation generation separately, for one or more databases successively. More details in the [[API (Application Programming Interface)|API]] page.
#During the documentation generation the software will __access only the repository__. The documented database might even be closed.
#During the current phase its progress is displayed continuously in the central text box.<br />Once started the documentation can be interrupted at any moment with the STOP button.
#At the end, the //table of content// is rebuilt to include the newly documented database(s).
Results of the documentation generation:
*The documentation is stored as a set of ''static HTML pages'' in a unique folder.<br />The name of the folder is, by default, the name name of the database file without its //.odb// suffix. This default value can be changed in the [[specific preferences|Preferences]] associated with the database.<br />At the start of the generation, the __output directory is cleaned from all *.html files__ it might contain.
*The status of the documentation is set to DONE in the repository.
*The log of the documentation generation is stored in the DOCLOG field of the relevant DATABASES record.
The produced documentation may be enriched with forms and dialogs screenshots. The screenshots must be stored (manually by the user) in the subfolders defined in the options or preferences.
The directory structure of the resulting documentation:
*Top: see //HTML pages output directory// in [[preferences|Preferences]]<br /> ... TOC.html ...
**Database1 (//short name//)<br /> ... all HTML pages ...
***DIALOGS<br /> ... dialog screenshots ...
***FORMS<br /> ... form screenshots ...
**Database2
**... idem ...
{{firstletter{
@@color:#930;B@@
}}}aseDocumenter identifies all the ''dependencies'' between items. E.g. a //query// might use one or more //tables//. Knowing exhaustively which items are used by which other items is invaluable for the developer of the application. This knowledge allows for example a detailed ''impact analysis'' of design changes.
Dependencies are of 2 types:
*''parent/child'': e.g. a //field// is the child of a //table//.
*''uses/used by'': e.g. a //query// uses a //table// or a //table// is used by a //query//. In //~BaseDocumenter//, such dependencies are very simply revealed by the use of ''__hyperlinks__''. Clicking on one of them makes the browser jump to the description of the linked item.
Sometimes it is even more complicated: a //control// can have a datasource, which is a //SQL statement// which on its turn refers to a //query// which on its turn again uses one or more //tables// or //queries// ...
[img[Dependencies|_images/dependencies.png]]
*In above graph yellow cells list which relations are identified by the //~BaseDocumenter// software.
*Orange cells identify dependencies between items that could possibly be included in a future release.
| !Date | !Version | !Description | !Dependencies |
|Aug 2018 | 0.6.0 |Show 1-N relationships between tables as [[relations|Relations]].<br />List secundary indexes and participating fields. | ~LibreOffice 6.0<br />(6.1 recommended). |
|Aug 2018 | 0.5.1 |Fix error when "Collect data statistics" option is deselected |~|
|Jul 2018 | 0.5.0 |First public release. |~|
{{firstletter{
@@color:#930;T@@
}}}he repository holds all the data collected during a database file scanning.
It must exist before any operation with the //~BaseDocumenter// software.
Physically it is a single ''.odb'' database file embedding a HSQLDB database.
!!Robustness
First of all, the repository is not considered as containing critical data.
Nevertheless, to avoid (logical) corruptions of the repository, the software makes a number of checks every time it opens it:
*Items without a corresponding database record are erased.
*Not terminated scans or documentation generations are removed.
*If there are duplicates on database names, only the newest is kept.
If, despite above measures, a (physical or logical) corruption still remains, then the repository can be deleted from the file system and rebuilt at the cost of re-setting the options and re-generating the documentation of each of your database files.
''__Regular operating system backups__ of the single file containing the repository can prevent painful failures''.
!!Creation and initialization of the repository
See the [[getting started|Install]] page.
!!Internal structure
After its initialization the repository contains exactly 2 tables. Read below their fields and meanings:
#''DATABASES''<br />[img[DATABASES table design|_images/databases_design.png]]<br />List of databases.
#''OBJECTS''<br />[img[OBJECTS table design|_images/objects_design.png]]<br />List of objects found in each database.
''The tables structure MUST NOT be altered''.
Similarly ''modifying data'' should be done ''only if you know what you are doing''.
However adding design elements is allowed.
As an example, the OBJECTS table will be more readable if you create (manually) a query with next __ direct SQL __:
//{{{
SELECT "DATABASEID",
"INDEX",
CASE "TYPE"
WHEN 0 THEN 'Database'
WHEN 1 THEN 'Table'
WHEN 2 THEN 'Query'
WHEN 3 THEN 'Form'
WHEN 4 THEN 'Report'
WHEN 5 THEN 'Dialog'
WHEN 6 THEN 'Module'
WHEN 7 THEN 'Toolbar'
WHEN 8 THEN 'Field'
WHEN 9 THEN 'SubForm'
WHEN 10 THEN 'Grid'
WHEN 11 THEN 'Control'
WHEN 12 THEN 'Event'
WHEN 13 THEN 'Procedure'
WHEN 14 THEN 'Toolbarcontrol'
ELSE '???'
END AS "ITEM TYPE",
"NAME",
"SHORTNAME",
CASE "PARENTTYPE"
WHEN 0 THEN 'Database'
WHEN 1 THEN 'Table'
WHEN 2 THEN 'Query'
WHEN 3 THEN 'Form'
WHEN 4 THEN 'Report'
WHEN 5 THEN 'Dialog'
WHEN 6 THEN 'Module'
WHEN 7 THEN 'Toolbar'
WHEN 8 THEN 'Field'
WHEN 9 THEN 'SubForm'
WHEN 10 THEN 'Grid'
WHEN 11 THEN 'Control'
WHEN 12 THEN 'Event'
WHEN 13 THEN 'Procedure'
WHEN 14 THEN 'Toolbarcontrol'
ELSE '???'
END AS "PARENT TYPE",
"PARENTINDEX",
"MISSING",
"USES",
"USEDBY",
CHAR_LENGTH ("PROPERTIES") AS "PROPLENGTH",
LEFT("PROPERTIES", 64000) AS "PROPLEFT"
FROM "OBJECTS"
//}}}
{{indent{''A documenter tool for //''~LibreOffice''// Base applications''
//[[BaseDocumenter|Home]]//
http://www.access2base.com/basedocumenter/basedocumenter.html
/***
|''Name:''|SpecificA2BPlugin|
|''Description:''|Forces readOnly to true or false. Useful to distribute a ReadOnly version of Access2Base help file. Set value to //true// in code below.|
!Code
***/
//{{{
readOnly = (window.location.protocol == "file:") ? false : config.options.chkHttpReadOnly;
//}}}
/***
|''Description:''|Modify tiddler tooltip for anonymisation.<br>Standard value: "%0 - %1, %2".|
!Code
***/
//{{{
merge(config.messages,{
tiddlerLinkTooltip: "%0 - Click to open",
});
//}}}
/***
|''Description''|Modify the header of the List macro.|
!Code
***/
//{{{
config.macros.list.all.prompt = "All topics in alphabetical order";
//}}}
/***
!~TiddlyWiki Classic Color Scheme
Designed by Jeremy Ruston
http://tiddlystyles.com/#theme:Classic
To use this color scheme copy the ~ClassicTiddlyWiki contents into a tiddler and name it 'StyleSheet' also grab the ~ClassicTemplate and copy its contents into a tiddler named 'PageTemplate'.
!Colors Used
*@@bgcolor(#630):color(#fff): #630@@
*@@bgcolor(#930): #930@@
*@@bgcolor(#996633): #963@@
*@@bgcolor(#c90): #c90@@
*@@bgcolor(#cf6): #cf6@@
*@@bgcolor(#cc9): #cc9@@
*@@bgcolor(#ba9): #ba9@@
*@@bgcolor(#996): #996@@
*@@bgcolor(#300):color(#fff): #300@@
*@@bgcolor(#000000):color(#fff): #000@@
*@@bgcolor(#666): #666@@
*@@bgcolor(#888): #888@@
*@@bgcolor(#aaa): #aaa@@
*@@bgcolor(#ddd): #ddd@@
*@@bgcolor(#eee): #eee@@
*@@bgcolor(#ffffff): #fff@@
*@@bgcolor(#f00): #f00@@
*@@bgcolor(#ff3): #ff3@@
!Generic Rules /%==============================================%/
***/
/*{{{*/
body {
background: #fff;
color: #000;
}
a{
color: #963;
}
a:hover{
background: #963;
color: #fff;
}
a img{
border: 0;
}
h1,h2,h3,h4,h5 {
background: #cc9;
}
/*}}}*/
/***
!Header /%==================================================%/
***/
/*{{{*/
.header{
background: #300;
}
.titleLine {
color: #fff;
padding: 5em 0em 1em .5em;
}
.titleLine a {
color: #cf6;
}
.titleLine a:hover {
background: transparent;
}
/*}}}*/
/***
!Main Menu /%=================================================%/
***/
/*{{{*/
#mainMenu .button {
color: #930;
}
#mainMenu .button:hover {
color: #cf6;
background: #930;
}
#mainMenu li{
list-style: none;
}
/*}}}*/
/***
!Sidebar options /%=================================================%/
~TiddlyLinks and buttons are treated identically in the sidebar and slider panel
***/
/*{{{*/
#sidebar {
background: #c90;
right: 0;
}
#sidebarOptions a{
color: #930;
border: 0;
margin: 0;
padding: .25em .5em;
}
#sidebarOptions a:hover {
color: #cf6;
background: #930;
}
#sidebarOptions a:active {
color: #930;
background: #cf6;
}
#sidebarOptions .sliderPanel {
background: #eea;
margin: 0;
}
#sidebarOptions .sliderPanel a {
color: #930;
}
#sidebarOptions .sliderPanel a:hover {
color: #cf6;
background: #930;
}
#sidebarOptions .sliderPanel a:active {
color: #930;
background: #cf6;
}
/*}}}*/
/***
!Sidebar tabs /%=================================================%/
***/
/*{{{*/
.tabSelected,.tabContents {
background: #eea;
border: 0;
}
.tabUnselected {
background: #c90;
}
#sidebarTabs {
background: #c90;
}
#sidebarTabs .tabSelected{
color: #cf6;
background: #963;
}
#sidebarTabs .tabUnselected {
color: #cf6;
background: #930;
}
#sidebarTabs .tabContents{
background: #963;
}
#sidebarTabs .txtMoreTab .tabSelected,
#sidebarTabs .txtMoreTab .tabSelected:hover{
background: #930;
color: #cf6;
}
#sidebarTabs .txtMoreTab .tabUnselected,
#sidebarTabs .txtMoreTab .tabUnselected:hover{
background: #300;
color: #cf6;
}
#sidebarTabs .txtMoreTab .tabContents {
background: #930;
}
#sidebarTabs .tabContents a {
color: #cf6;
border: 0;
}
#sidebarTabs .button.highlight,
#sidebarTabs .tabContents a:hover {
background: #cf6;
color: #300;
}
/*}}}*/
/***
!Message Area /%=================================================%/
***/
/*{{{*/
#messageArea {
background: #930;
color: #fff;
}
#messageArea a:link, #messageArea a:visited {
color: #c90;
}
#messageArea a:hover {
color: #963;
background: transparent;
}
#messageArea a:active {
color: #fff;
}
/*}}}*/
/***
!Popup /%=================================================%/
***/
/*{{{*/
.popup {
background: #eea;
border: 1px solid #930;
}
.popup hr {
color: #963;
background: #963;
border-bottom: 1px;
}
.popup li.disabled {
color: #ba9;
}
.popup li a, .popup li a:visited {
color: #300;
}
.popup li a:hover {
background: #930;
color: #eea;
}
/*}}}*/
/***
!Tiddler Display /%=================================================%/
***/
/*{{{*/
.tiddler .button {
color: #930;
}
.tiddler .button:hover {
color: #cf6;
background: #930;
}
.tiddler .button:active {
color: #fff;
background: #c90;
}
.shadow .title {
color: #888;
}
.title {
color: #422;
}
.subtitle {
color: #866;
}
.toolbar {
color: #aaa;
}
.toolbar a,
.toolbar a:hover{
border: 0;
}
.tagging, .tagged {
border: 1px solid #fff;
background-color: #ffc;
}
.selected .tagging, .selected .tagged {
border: 1px solid #aa6;
background-color: #ffc;
}
.tagging .listTitle, .tagged .listTitle {
color: #999999;
}
.footer {
color: #ddd;
}
.selected .footer {
color: #888;
}
.sparkline {
background: #eea;
border: 0;
}
.sparktick {
background: #930;
}
.errorButton {
color: #ff0;
background: #f00;
}
.zoomer {
color: #963;
border: 1px solid #963;
}
/*}}}*/
/***
''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/
***/
/*{{{*/
.viewer .button {
background: #c90;
color: #300;
border-right: 1px solid #300;
border-bottom: 1px solid #300;
}
.viewer .button:hover {
background: #eea;
color: #c90;
}
.viewer .imageLink{
background: transparent;
}
.viewer blockquote {
border-left: 3px solid #666;
}
.viewer table {
border: 2px solid #303030;
}
.viewer th, thead td {
background: #996;
border: 1px solid #606060;
color: #fff;
}
.viewer td, .viewer tr {
border: 1px solid #606060;
}
.viewer pre {
border: 1px solid #963;
background: #eea;
}
.viewer code {
color: #630;
}
.viewer hr {
border: 0;
border-top: dashed 1px #606060;
color: #666;
}
.highlight, .marked {
background: #ff3;
}
/*}}}*/
/***
''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/
***/
/*{{{*/
.editor input {
border: 1px solid #000;
}
.editor textarea {
border: 1px solid #000;
width: 100%;
}
.editorFooter {
color: #aaa;
}
.editorFooter a {
color: #930;
}
.editorFooter a:hover {
color: #cf6;
background: #930;
}
.editorFooter a:active {
color: #fff;
background: #c90;
}
/*}}}*/
/***
!Specific addition for ~Access2Base /%=================================================%/
***/
/*{{{*/
@media print {#mainMenu {display: none ! important;}}
@media print {#topMenu {display: none ! important;}}
@media print {#sidebar {display: none ! important;}}
@media print {#messageArea {display: none ! important;}}
@media print {#toolbar {display: none ! important;}}
@media print {.header {display: none ! important;}}
@media print {.tiddler .subtitle {display: none ! important;}}
@media print {.tiddler .toolbar {display; none ! important; }}
@media print {.tiddler .tagging {display; none ! important; }}
@media print {.tiddler .tagged {display; none ! important; }}
#mainMenu {
position:absolute;
left:0;
width:13em;
text-align:right;
line-height:1.6em;
padding:1.5em 0.5em 0.5em 0.5em;
font-size:1.1em;
}
#displayArea {
margin:1em 17em 0 16em;
}
.titleLine {
color: #fff;
padding: 3em 0em 1em .5em;
}
.firstletter{ float:left; width:0.75em; font-size:400%; font-family:times,arial; line-height:60%; }
.tiddler .subtitle { display:none; }
/*}}}*/
/*~StyleSheetShortcuts*/
{{firstletter{
@@color:#930;T@@
}}}o make the HTML documentation produced by ~BaseDocumenter visually more attractive, many classes are inserted in the HTML tags.
It is easy to refer to these classes in ''stylesheets''.
The used CSS stylesheets should be invoked from the [[template|Templates]] indicated by your [[preferences|Preferences]].
!!List of classes
!!!Table classes
One class by main table generated by ~BaseDocumenter, to not confuse them with other tables present in the template and to better target their subclasses.
| !Class | !Tags | !Description |
|{{{dbdatatable}}} | {{{<table>}}} |The effective data produced for the current documentation page. |
|{{{dbtoctable}}} |~|The horizontal table of contents: 1 row and 1 column by item type. |
|{{{dbtoctree}}} | {{{<ul>}}} |The vertical table of contents inserted as an unordered list. |
|{{{dbtoctreeheader}}} | {{{<span>}}} |The first items of the vertical table of contents: the general TOC page and the actual database name. |
!!!Data classes
| !Class | !Tags | !Typical usage |
|{{{odd}}}<br />{{{even}}} | {{{<tr>}}} |To display alternate colors or backgrounds..|
|{{{firstrow}}}<br />{{{lastrow}}} |~|To define specific borders above or under the first or the last row. |
|{{{firstcol}}}<br />{{{lastcol}}} | {{{<th>}}}<br />{{{<td>}}} |To define specific borders on the left or the right of the first or the last column. |
|{{{char}}}<br />{{{numeric}}}<br />{{{negative}}}<br />{{{date}}}<br />{{{bool}}}<br />{{{false}}}<br />{{{null}}} | {{{<td>}}} |To define display effects depending on the content of the table cell.<br />Like right justifying numbers, red fonts for negative numbers, special background for empty cells, etc. |
!!!SQL classes
| !Class | !Tags | !Description |
|{{{sqlquote}}}<br />{{{sqlkeyword}}}<br />{{{sqlfunction}}}<br />{{{sqlnumber}}}<br />{{{sqlword}}}<br />{{{sqlcomment}}}<br />{{{sqlvariable}}} | {{{<span>}}} |Strings, keywords, builtin functions, constants, fields, comment and variables in SQL statements. |
|{{{sqltablename}}}<br />{{{sqlqueryname}}} |~|Hyperlinks to external references. |
|{{{sqlerror}}} |~|Parsing or SQL syntax errors. |
!!!Basic scripts classes
| !Class | !Tags | !Description |
|{{{scriptkeyword}}}<br />{{{scriptfunction}}}<br />{{{scriptconstant}}}<br />{{{scriptvardef}}}<br />{{{scriptstring}}}<br />{{{scriptnumber}}}<br />{{{scriptidentifier}}}<br />{{{scriptoperator}}}<br />{{{scriptcomment}}} | {{{<span>}}} |Basic keywords, builtin functions, constants, type definitions, strings, numbers, identifiers, arythmetic operators and comments. |
|{{{scripttablename}}}<br />{{{scriptqueryname}}}<br />{{{scriptformname}}}<br />{{{scriptdialogname}}}<br />{{{scriptprocname}}} |~|Hyperlinks to external references. |
|{{{scripterror}}} |~|Parsing or Basic syntax errors. |
Example: next styles define a layout for Basic scripts that looks more or less like the default layout of the same scripts in the ~LibreOffice Basic IDE.
//{{{
.dbdatatable .scriptidentifier {color: green;}
.dbdatatable .scriptkeyword {color: blue;}
.dbdatatable .scriptfunction {color: blue;}
.dbdatatable .scriptcomment {color: gray;}
.dbdatatable .scriptvardef {color: blue;}
.dbdatatable .scriptstring {color: red;}
.dbdatatable .scriptnumber {color: red;}
.dbdatatable .scriptconstant {color: blue;}
//}}}
/***
|''Name:''|TagsTreePlugin|
|''Description:''|Displays tags hierachy as a tree of tagged tiddlers.<br>Can be used to create dynamic outline navigation.|
|''Version:''|1.0.1|
|''Date:''|Jan 04,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Demo
On the plugin [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] :
*Try to tag some <<newTiddler>> with a tag displayed in the menu and edit MainMenu.
*Look at some tags like [[Plugins]] or [[menu]].
!Installation
#import the plugin,
#save and reload,
#optionally, edit TagsTreeStyleSheet.
! Usage
{{{<<tagsTree>>}}} macro accepts the following //optional// parameters.
|!#|!parameter|!description|!by default|
|1|{{{root}}}|Uses {{{root}}} tag as tree root|- In a //tiddler// content or template : uses the tiddler as root tag.<br>- In the //page// content or template (by ex MainMenu) : displays all untagged tags.|
|2|{{{excludeTag}}}|Excludes all such tagged tiddlers from the tree|Uses default excludeLists tag|
|3|{{{level}}}|Expands nodes until level {{{level}}}.<br>Value {{{0}}} hides expand/collapse buttons.|Nodes are collapsed on first level|
|4|{{{depth}}}|Hierachy depth|6 levels depth (H1 to H6 header styles)|
|5|{{{sortField}}}|Alternate sort field. By example : "index".|Sorts tags and tiddlers alphabetically (on their title)|
|6|{{{labelField}}}|Alertnate label field. By example : "label".|Displays tiddler's title|
!Useful addons
*[[FieldsEditorPlugin]] : //create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.
*[[TaggerPlugin]] : Provides a drop down listing current tiddler tags, and allowing toggling of tags.
!Advanced Users
You can change the global defaults for TagsTreePlugin, like default {{{level}}} value or level styles, by editing or overriding the first config.macros.tagsTree attributes below.
!Code
***/
//{{{
config.macros.tagsTree = {
expand : "+",
collapse : "–",
depth : 6,
level : 1,
sortField : "",
labelField : "",
styles : ["h1","h2","h3","h4","h5","h6"],
trees : {}
}
config.macros.tagsTree.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
var root = params[0] ? params[0] : (tiddler ? tiddler.title : null);
var excludeTag = params[1] ? params[1] : "excludeTagsTree";
var level = params[2] ? params[2] : config.macros.tagsTree.level;
var depth = params[3] ? params[3] : config.macros.tagsTree.depth;
var sortField = params[4] ? params[4] : config.macros.tagsTree.sortField;
var labelField = params[5] ? params[5] : config.macros.tagsTree.labelField;
var showButtons = (level>0);
var id = config.macros.tagsTree.getId(place);
if (config.macros.tagsTree.trees[id]==undefined) config.macros.tagsTree.trees[id]={};
config.macros.tagsTree.createSubTree(place,id,root,excludeTag,[],level>0 ? level : 1,depth, sortField, labelField,showButtons);
}
config.macros.tagsTree.createSubTree = function(place, id, root, excludeTag, ancestors, level, depth, sortField, labelField,showButtons){
var childNodes = root ? this.getChildNodes(root, ancestors) : this.getRootTags(excludeTag);
var isOpen = (level>0) || (!showButtons);
if (root && this.trees[id][root]!=undefined) isOpen = this.trees[id][root];
if (root && ancestors.length) {
var t = store.getTiddler(root);
if (childNodes.length && depth>0) {
var wrapper = createTiddlyElement(place , this.styles[Math.min(Math.max(ancestors.length,1),6)-1],null,"branch");
if (showButtons) {
b = createTiddlyButton(wrapper, isOpen ? config.macros.tagsTree.collapse : config.macros.tagsTree.expand, null, config.macros.tagsTree.onClick);
b.setAttribute("treeId",id);
b.setAttribute("tiddler",root);
}
createTiddlyText(createTiddlyLink(wrapper, root),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
}
else
createTiddlyText(createTiddlyLink(place, root,false,"leaf"),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
}
if (childNodes.length && depth) {
var d = createTiddlyElement(place,"div",null,"subtree");
d.style.display= isOpen ? "block" : "none";
if (sortField)
childNodes.sort(function(a, b){
var fa=a.fields[sortField];
var fb=b.fields[sortField];
return (fa==undefined && fb==undefined) ? a.title < b.title ? -1 : a.title > b.title ? 1 : 0 : (fa==undefined && fb!=undefined) ? 1 :(fa!=undefined && fb==undefined) ? -1 : fa < fb ? -1 : fa > fb ? 1 : 0;
})
for (var cpt=0; cpt<childNodes.length; cpt++)
this.createSubTree(d, id, childNodes[cpt].title, excludeTag, ancestors.concat(root), level-1, depth-1, sortField, labelField, showButtons);
}
}
config.macros.tagsTree.onClick = function(e){
var id = this.getAttribute("treeId");
var tiddler = this.getAttribute("tiddler");
var n = this.parentNode.nextSibling;
var isOpen = n.style.display != "none";
if(config.options.chkAnimate && anim && typeof Slider == "function")
anim.startAnimating(new Slider(n,!isOpen,null,"none"));
else
n.style.display = isOpen ? "none" : "block";
this.firstChild.nodeValue = isOpen ? config.macros.tagsTree.expand : config.macros.tagsTree.collapse;
config.macros.tagsTree.trees[id][tiddler]=!isOpen;
return false;
}
config.macros.tagsTree.getChildNodes = function(root ,ancestors){
var childs = store.getTaggedTiddlers(root);
var result = new Array();
for (var cpt=0; cpt<childs.length; cpt++)
if (childs[cpt].title!=root && ancestors.indexOf(childs[cpt].title)==-1) result.push(childs[cpt]);
return result;
}
config.macros.tagsTree.getRootTags = function(excludeTag){
var tags = store.getTags(excludeTag);
tags.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
var result = new Array();
for (var cpt=0; cpt<tags.length; cpt++) {
var t = store.getTiddler(tags[cpt][0]);
if (!t || t.tags.length==0) result.push(t ? t : {title:tags[cpt][0],fields:{}});
}
return result;
}
config.macros.tagsTree.getId = function(element){
while (!element.id && element.parentNode) element=element.parentNode;
return element.id ? element.id : "<html>";
}
config.shadowTiddlers.TagsTreeStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".leaf, .subtree {display:block; margin-left : 0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".subtree {margin-bottom:0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="#mainMenu {text-align:left}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".branch .button {border:1px solid #DDD; color:#AAA;font-size:9px;padding:0 2px;margin-right:0.3em;vertical-align:middle;text-align:center;}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="/*}}}*/";
store.addNotification("TagsTreeStyleSheet", refreshStyles);
config.shadowTiddlers.MainMenu="<<tagsTree>>"
config.shadowTiddlers.PageTemplate = config.shadowTiddlers.PageTemplate.replace(/id='mainMenu' refresh='content' /,"id='mainMenu' refresh='content' force='true' ")
//}}}
/*{{{*/
.leaf, .subtree {
display:block;
margin-left : 0.5em
}
.subtree {
margin-bottom:0.5em
}
#mainMenu {
text-align:left
}
.branch {
border:1px solid #DDD;
color:#AAA;
font-size:12px;
padding:0 2px;
margin-right:0.3em;
vertical-align:middle;
text-align:left;
}
.button {
border:1px solid #DDD;
font-size:12px;
padding:0 2px;
margin-right:0.7em;
vertical-align:
middle;
text-align:center;
}
/*}}}*/
{{firstletter{
@@color:#930;B@@
}}}aseDocumenter produces the documentation of the scanned database files as a ''set of static HTML pages''.
*Exactly one ''table of contents'': TOC.html.
*As many HTML pages as needed by database file, grouped together in one single directory by database.
All those pages can be personalized with __page templates__.
*One template for the //table of contents//.
*One template for all the pages related to a database file. In practice, often the same template is used for ALL database files.
A template is a normal standard HTML page. It might contain references to javascript effects, [[CSS (cascading stylesheets)|Styling]] files, or whatever the user finds useful to improve the readability of the final documentation, including a company logo.
A template contains ''tokens'' : a token marks the place where ~BaseDocumenter should insert the information corresponding with the given token.
The __minimal__ template, i.e. the template used by the software when no template at all is defined in the [[preferences|Preferences]] is the following:
//{{{
<!DOCTYPE html>
<html>
<head>
<title><!--Template_Title--></title>
</head>
<body>
%DBDATATABLE%
</body>
</html>
//}}}
The template contains in this example only the mandatory token: //%DBDATATABLE%//.
!!Tokens
| !Token | !In TOC | !Description |
|%DBNAME% ||Short name of the database.<br />Is also identical with the directory name whare the documentation is stored. |
|%DBLOCATION% ||Full path of the database file (//.odb//). |
|%DBVERSION% ||RDBMS engine name and version (e.g. {{{HSQL Database Engine 1.8.0}}}). |
|%USER% ||Login name of the user who produced the documentation. |
|%NOW% | Y |Actual date and time. |
|%DBFILEDATE% ||Database file save date and time. |
|%SCANTIME% ||Database scan date and time. |
|%DBDATATABLE% | Y |The effective data of the page, encapsulated between<br /> {{{<table class="dbdatatable">}}}<br /> {{{... effective data ...}}}<br /> {{{</table>}}}<br />tags. |
|%DBTOCTABLE% ||A __horizontal__ table of contents for the database file presented as a single-row table, encapsulated between<br /> {{{<table class="dbtoctable">}}}<br /> {{{... table of contents ...}}}<br /> {{{</table>}}}<br />tags. |
|%DBTOCTREE% ||A __vertical__ table of contents for the database file presented as a unordered list, encapsulated between<br /> {{{<ul class="dbtoctree">}}}<br /> {{{... table of contents including a detailed list of items...}}}<br /> {{{</ul>}}}<br />tags. |
*To avoid a useless redundancy, %DBTOCTABLE% and %DBTOCTREE% are seldom used together.
*The last 3 tokens are combined with //class// attributes. To know more about the numerous ways to influence the display, have a look at the [[CSS styles|Styling]] page.
!!Examples
Two different templates (1 for the //table of contents// and 1 for the data) are used in the [[examples|Examples]] pages. They make use of stylesheets and javascript. They might help you to build your own templates. Feel free to ''DOWNLOAD'' them from ''[[HERE|http://www.access2base.com/basedocumenter/_download/Templates.zip]]'' and rework them for your own uses.
Next people have directly or indirectly contributed to the birth of the ~BaseDocumenter application:
*''Thomas Koester'', author of the [[Access Dependency Checker|http://www.accessdependencychecker.com/]]. I was in another life user of its version 1. A number of his very good ideas inspired me in the design of //~BaseDocumenter//.
*''Bernard Marcelly'' because I would not have even started the project without the existence of ~XRayTool, the inspector of API objects, See [[here|http://bernard.marcelly.perso.sfr.fr/index2.html]]. Additionally I scanned his code in one of the examples.
*''Jeremy Ruston'' who developed the remarkable personal wiki which served as template for the documentation of ~BaseDocumenter. See [[TiddlyWiki, a reusable non-linear personal web notebook|http://www.tiddlywiki.com/]].
*''Gisbert Friege'' who
**was an early adopter of the software and, as such, proposed a huge number of improvements, most already implemented and others still to come,
**is the author of the biggest example on this site: [[GenoBase|http://www.access2base.com/basedocumenter/examples/GenoBase/Database.html]],
**translated the software in german.
*''Robert Großkopf'' who is the author of the __Base Handbook__ and of its examples. We exchanged also a number of ideas and code snippets that helped me a lot in building proofs of concept.
*''~Jean-Francois Nifenecker'' and ''Villeroy'', who are the authors of one or more databases boldly used by me in the examples.
Many thanks to all of them.
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demos
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], open several tiddlers to use the tabs bar.
!Installation
#import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
#save and reload
#''if you're using a custom [[PageTemplate]]'', add {{{<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>}}} before {{{<div id='tiddlerDisplay'></div>}}}
#optionally, adjust StyleSheetTiddlersBar
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed.
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab = config.options.chkHideTabsBarWhenSingleTab ? config.options.chkHideTabsBarWhenSingleTab : false;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
tooltip : "see ",
tooltipClose : "click here to close this tab",
tooltipSave : "click here to save this tab",
promptRename : "Enter tiddler new name",
currentTiddler : "",
previousState : false,
previousKey : config.options.txtPreviousTabKey,
nextKey : config.options.txtNextTabKey,
tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
handler: function(place,macroName,params) {
var previous = null;
if (config.macros.tiddlersBar.isShown())
story.forEachTiddler(function(title,e){
if (title==config.macros.tiddlersBar.currentTiddler){
var d = createTiddlyElement(null,"span",null,"tab tabSelected");
config.macros.tiddlersBar.createActiveTabButton(d,title);
if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
previous = "active";
}
else {
var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
btn.setAttribute("tiddler", title);
if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
previous=btn;
}
var isDirty =story.isDirty(title);
var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
c.setAttribute("tiddler", title);
if (place.childNodes) {
place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
place.insertBefore(d,place.firstChild);
}
else place.appendChild(d);
})
},
refresh: function(place,params){
removeChildren(place);
config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
story.refreshAllTiddlers();
if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
}
},
isShown : function(){
if (config.options.chkDisableTabsBar) return false;
if (!config.options.chkHideTabsBarWhenSingleTab) return true;
var cpt=0;
story.forEachTiddler(function(){cpt++});
return (cpt>1);
},
selectNextTab : function(){ //used when the current tab is closed (to select another tab)
var previous="";
story.forEachTiddler(function(title){
if (!config.macros.tiddlersBar.currentTiddler) {
story.displayTiddler(null,title);
return;
}
if (title==config.macros.tiddlersBar.currentTiddler) {
if (previous) {
story.displayTiddler(null,previous);
return;
}
else config.macros.tiddlersBar.currentTiddler=""; // so next tab will be selected
}
else previous=title;
});
},
onSelectTab : function(e){
var t = this.getAttribute("tiddler");
if (t) story.displayTiddler(null,t);
return false;
},
onTabClose : function(e){
var t = this.getAttribute("tiddler");
if (t) {
if(story.hasChanges(t) && !readOnly) {
if(!confirm(config.commands.cancelTiddler.warning.format([t])))
return false;
}
story.closeTiddler(t);
}
return false;
},
onTabSave : function(e) {
var t = this.getAttribute("tiddler");
if (!e) e=window.event;
if (t) config.commands.saveTiddler.handler(e,null,t);
return false;
},
onSelectedTabButtonClick : function(event,src,title) {
var t = this.getAttribute("tiddler");
if (!event) event=window.event;
if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
return false;
},
onTiddlersBarAction: function(event) {
var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
},
createActiveTabButton : function(place,title) {
if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
btn.setAttribute("tiddler", title);
}
else
createTiddlyText(place,title);
}
}
story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;
story.closeTiddler = function(title,animate,unused) {
if (title==config.macros.tiddlersBar.currentTiddler)
config.macros.tiddlersBar.selectNextTab();
story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
var e=document.getElementById("tiddlersBar");
if (e) config.macros.tiddlersBar.refresh(e,null);
}
story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;
if (config.macros.tiddlersBar.isShown()) {
story.forEachTiddler(function(t,e){
if (t!=title) e.style.display="none";
else e.style.display="";
})
config.macros.tiddlersBar.currentTiddler=title;
}
var e=document.getElementById("tiddlersBar");
if (e) config.macros.tiddlersBar.refresh(e,null);
}
var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
coreRefreshPageTemplate(title);
if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}
ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)
config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);
config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");
//}}}
/***
|Name|ToggleSideBarMacro|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#ToggleSideBarMacro|
|Version|1.0|
|Requires|~TW2.x|
!Description:
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.
!Demo
<<toggleSideBar "Toggle Sidebar">>
!Usage:
{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)
You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}
!History
*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour.
*20-07-06: version 0.11
*27-04-06: version 0.1: working.
!Code
***/
//{{{
config.macros.toggleSideBar={};
config.macros.toggleSideBar.settings={
styleHide : "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
styleShow : " ",
arrow1: "«",
arrow2: "»"
};
config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
{
var tooltip= params[1]||'toggle sidebar';
var mode = (params[2] && params[2]=="hide")? "hide":"show";
var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
var label= (params[0]&¶ms[0]!='.')?params[0]+" "+arrow:arrow;
var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
if (mode == "hide")
{
(document.getElementById("sidebar")).setAttribute("toggle","hide");
setStylesheet(this.settings.styleHide,"ToggleSideBarStyles");
}
};
config.macros.toggleSideBar.onToggleSideBar = function(){
var sidebar = document.getElementById("sidebar");
var settings = config.macros.toggleSideBar.settings;
if (sidebar.getAttribute("toggle")=='hide')
{
setStylesheet(settings.styleShow,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","show");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);
}
else
{
setStylesheet(settings.styleHide,"ToggleSideBarStyles");
sidebar.setAttribute("toggle","hide");
this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);
}
return false;
}
setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");
//}}}
|~ViewToolbar|closeTiddler closeOthers +editTiddler > permalink references|
|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<div style='float:center;' macro='tiddler BookMarkTiddler'></div>
<!--}}}-->