{{{
@TECHREPORT{AgaGel:03,
author = {Agarwal, D. K. and Gelfand, A. E.},
title = {Slice Gibbs sampling for simulation based fitting of spatial data models},
institution = {University of Connecticut},
year = {2003},
}
@ARTICLE{Ait:91,
author = {Aitkin, M.},
title = {Posterior Bayes factors},
journal = {Journal of the Royal Statistical Society B},
year = {1991},
volume = {53},
pages = {111-142},
}
@ARTICLE{AlbChi:93,
author = {Albert, J. H. and Chib, S.},
title = {Bayesian Analysis of Binary and Polychotomous Response Data},
journal = {Journal of the American Statistical Association},
year = {1993},
volume = {88},
number = {422},
pages = {669-679},
}
@ARTICLE{BerChe:93,
author = {Berger, J. O. and Chen, M.- H.},
title = {Predicting retirement patterns: prediction for a multinomial distribution with constrained parameter space},
journal = {The Statistician},
year = {1993},
volume = {42},
pages = {427-443},
}
@ARTICLE{BesGre:93,
author = {Besag, J. and Green, P. J.},
title = {Spatial Statistics and Bayesian Computation},
journal = {Journal of the Royal Statistical Society B},
year = {1993},
volume = {55},
number = {1},
pages = {25-37},
}
@MANUAL{Coda:97,
title = {CODA - Convergence Diagnosis and Output Analysis software for Gibbs sampling output: Version 0.4},
author = {Best, N. and Cowles, M. K. and Vines, K.},
organization = {MRC Biostatistics Unit},
address = {Cambrigde},
year = {1997},
}
@TECHREPORT{Bro.R:95,
author = {Brooks, S. and Roberts, G.},
title = {Assessing convergence of Markov chain Monte Carlo algorithms},
institution = {Department of Pure Mathematics and Mathematical Statistics, University of Cambridge},
year = {1995},
number = {12},
}
@ARTICLE{Car.C:95,
author = {Carlin, B. P. and Chib, S.},
title = {Bayesian model choice via Markov chain Monte Carlo methods},
journal = {Journal of the Royal Statistical Society B},
year = {1995},
volume = {57},
pages = {473-484},
}
@ARTICLE{Cas.G:92,
author = {Casella, G. and George, E. I.},
title = {Explaining the Gibbs Sampler},
journal = {The American Statistician},
year = {1992},
volume = {46},
number = {3},
pages = {167-174},
}
@ARTICLE{CasLAvRob:01,
author = {Casella, G. and Lavine, M. and Robert, C. P.},
title = {Explaining the Perfect Sampler},
journal = {The American Statistician},
year = {2001},
volume = {55},
number = {4},
pages = {299-305},
}
@ARTICLE{ChaVan:01,
author = {Chauveau, D. and Vandekerkhove, P.},
title = {Improving convergence of the Hastings-Metropolis Algorithm with a learning proposal},
journal = {Scandinavian Journal of Statistics},
year = {2001},
volume = {29},
number = {1},
pages = {13-29},
}
@TECHREPORT{Che,
author = {Chen, M.-H.},
title = {Markov Chain Monte Carlo Sampling for Evaluating Multidimensional Integrals With Application to Bayesian Computation},
institution = {Dept of Mathematical Sciences, WPI},
}
@ARTICLE{Chi.G:95,
author = {Chib, S. and Greenberg, E.},
title = {Understanding the Metropolis-Hastings algorithm},
journal = {The American Statistician},
year = {1995},
volume = {49},
number = {4},
pages = {327-335},
}
@ARTICLE{Coo.B:95,
author = {Cook, P. and Broemeling, L.D.},
title = {Bayesian statistics using Mathematica},
journal = {The American Statistician},
year = {1995},
volume = {49},
pages = {70-76},
}
@ARTICLE{Cow.C:96,
author = {Cowles, M. K. and Carlin, B. P.},
title = {Markov chain Monte Carlo convergence diagnostics: a comparative review},
journal = {Journal of the American Statistical Association},
year = {1996},
volume = {91},
pages = {883-904},
}
@ARTICLE{DamWakWal:99,
author = {Damien, P. and Wakefield, J. and Walker, S.},
title = {Gibbs sampling for Bayesian non-conjugate and hierarchical models by using auxiliary variables},
journal = {Journal of the Royal Statistical Society B},
year = {1999},
volume = {61},
number = {Part 2},
pages = {331-344},
}
@TECHREPORT{DouGodRob,
author = {Doucet, A. and Godsill, S. J. and Robert, C. P.},
title = {Marginal Maximum A Posteriori Estimation using Markov Chain Monte Carlo},
institution = {Signal Processing Group, University of Cambridge},
}
@ARTICLE{Gel.S:90,
author = {Gelfand, A. E. and Smith, A. F. M.},
title = {Sampling-based approaches to calculating marginal densities},
journal = {Journal of the American Statistical Association},
year = {1990},
volume = {85},
number = {410},
pages = {398-409},
}
@ARTICLE{GelSmiLee:92,
author = {Gelfand, A. E. and Smith, A. F. M. and Lee, T.-M.},
title = {Bayesian Analysis of Constrained Parameter and Truncated Data Problems Using Gibbs Sampling},
journal = {Journal of the American Statistical Association},
year = {1992},
volume = {87},
number = {418},
pages = {523-532},
}
@ARTICLE{Gel.D:94,
author = {Gelfand, A. E. G. and Dey, D. K.},
title = {Bayesian model choice: asymptotics and exact calculations},
journal = {Journal of the Royal Statistical Society B},
year = {1994},
volume = {56},
pages = {501-514},
}
@ARTICLE{Gel.H.R.S:90,
author = {Gelfand, A. E. G. and Hills, S. E. and Racine-Poon, A. and Smith, A. F. M.},
title = {Illustration of Bayesian inference in normal data models using Gibbs sampling},
journal = {Journal of the American Statistical Association},
year = {1990},
volume = {85},
pages = {972-985},
}
@INCOLLECTION{GelMen:96,
author = {Gelman, A. and Meng, X.-L.},
title = {Model checking and model improvement},
booktitle = {Markov Chain Monte Carlo in Practice},
publisher = {Chapman and Hall, London},
year = {1996},
editor = {Gilks, W. R. and Richardson, S. and Spiegelhalter, D. J.},
pages = {189-202},
}
@ARTICLE{Gem.G:84,
author = {Geman, S. and Geman, D.},
title = {Stochastic relaxation, Gibbs distributions, and the Bayesian restoration of images},
journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
year = {1984},
volume = {6},
pages = {721-741},
}
@INPROCEEDINGS{Gew:92,
author = {Geweke, J.},
title = {Evaluating the accuracy of sampling-based approaches to calculating posterior moments},
booktitle = {Bayesian Statistics 4},
year = {1992},
editor = {Bernardo, J. M. and Berger, J. O. and Dawid, A. P. and Smith, A. F. M.},
pages = {169-193},
address = {Oxford},
publisher = {University Press},
}
@ARTICLE{Gey:92,
author = {Geyer, C. J.},
title = {Pratical Markov Chain Monte Carlo},
journal = {Statistical Science},
year = {1992},
volume = {7},
number = {4},
pages = {473-511},
}
@ARTICLE{Gil.C.S.B.M.S.K:93,
author = {Gilks, W. R. and Clayton, D. G. and Spiegelhalter, D. J. and Best, N. G. and McNeil, A. J. and Sharples, L. D. and Kirby, A. J.},
title = {Modelling complexity: applications of Gibbs sampling in medicine},
journal = {Journal of the Royal Statistical Society B},
year = {1993},
volume = {55},
pages = {39-52},
}
@ARTICLE{GilTS:94,
author = {Gilks, W. R. and Thomas, A. and Spiegelhalter, D. J.},
title = {A language and program for complex Bayesian modelling},
journal = {The Statistician},
year = {1994},
volume = {43},
pages = {169-178},
}
@ARTICLE{Gil.B.T:95,
author = {Gilks, W.R. and Best, N.G. and Tan, K.K.C.},
title = {Adaptive rejection Metropolis sampling within Gibbs sampling},
journal = {Applied Statistics},
year = {1995},
volume = {44},
pages = {455-472},
}
@ARTICLE{Gil.W:92,
author = {Gilks, W.R. and Wild, P.},
title = {Adaptive rejection sampling for Gibbs sampling},
journal = {Applied Statistics},
year = {1992},
volume = {41},
pages = {337-348},
}
@TECHREPORT{GreMir,
author = {Green, P. J. and Mira, A.},
title = {Delayed Rejection in Reversible Jump Metropolis-Hastings},
}
@ARTICLE{HanCar:01,
author = {Han, C. and Carlin, B. R.},
title = {Markov Chain Monte Carlo Methods for Computing Bayes Factors: A Comparative Review},
journal = {Journal of the American Statistical Association},
year = {2001},
volume = {96},
number = {455},
pages = {1122-1132},
}
@ARTICLE{Has:70,
author = {Hastings, W.K.},
title = {Monte Carlo sampling methods using Markov chains and their applications},
journal = {Biometrika},
year = {1970},
volume = {57},
pages = {97-109},
}
@ARTICLE{Hei.W:83,
author = {Heidelberger, P. and Welch, P.},
title = {Simulation run length control in the presence of an initial transient},
journal = {Operations Research},
year = {1983},
volume = {31},
pages = {1109-1144},
}
@TECHREPORT{Hig:96,
author = {Higdon, D. M.},
title = {Auxiliary Variable Methods for Markov Chain Monte Carlo with Applications},
institution = {Jasa},
year = {1996},
journal = {Jasa Theory and Methods},
}
@INPROCEEDINGS{Hil.S:92,
author = {Hills, S.E. and Smith, A.F.M.},
title = {Parameterization issues in Bayesian inference},
booktitle = {Bayesian Statistics 4},
year = {1992},
editor = {Bernardo, J.M. and Berger, J.O. and Dawid, A.P. and Smith, A.F.M.},
pages = {227-246},
publisher = {Oxford University Press},
}
@ARTICLE{IhaGen:96,
author = {Ihaka, R. and Gentleman, R.},
title = {R: A Language for Data Analysis and Graphics},
journal = {Journal of Computational and Graphical Statistics},
year = {1996},
volume = {5},
number = {3},
pages = {299-314},
}
@ARTICLE{Ing:94,
author = {Ingrassia, S.},
title = {On the rate of convergence of the Metropolis algorithm and Gibbs sampler by geometric bounds},
journal = {The Annals of Applied Probability},
year = {1994},
volume = {31},
pages = {347-389},
}
@ARTICLE{JonHob:01,
author = {Jones, G. L. and Hobert, J. P.},
title = {Honest Exploration of Intractable Probability Distributions via Markov Chain Monte Carlo},
journal = {Statistical Science},
year = {2001},
volume = {16},
number = {4},
pages = {312-334},
}
@ARTICLE{KasRaf:95,
author = {Kass, R. E. and Raftery, A.E.},
title = {Bayes Factors},
journal = {Journal of the American Statistical Association},
year = {1995},
volume = {90},
number = {430},
pages = {773-795},
}
@ARTICLE{Kas.C.G.N:98,
author = {Kass, R.E. and Carlin, B.P. and Gelman, A. and Neal, R.M.},
title = {Markov chain Monte Carlo in practice: a roundtable discussion},
journal = {The American Statistician},
year = {1998},
volume = {52},
pages = {93-100},
}
@INPROCEEDINGS{Key.P.S:98,
author = {Key, J.T. and Pericchi, L.R. and Smith, A.F.M.},
title = {Bayesian model choice: what and why?},
booktitle = {Bayesian Statistics 6},
year = {1998},
editor = {Bernardo, J.M. and Berger, J.O. and Dawid, A.P. and Smith, A.F.M.},
pages = {0-0},
publisher = {Oxford University Press},
}
@ARTICLE{Leo:78,
author = {Leonard, T.},
title = {Density estimation, stochastic processes and prior information},
journal = {Journal of the Royal Statistical Society B},
year = {1978},
volume = {40},
pages = {113-146},
}
@TECHREPORT{Liu,
author = {Liu, J. S.},
title = {Metropolized Independent Sampling with Comparisons to Rejection Sampling and Importance Sampling},
institution = {Department of Statistics, Stanford University},
}
@TECHREPORT{Liu2,
author = {Liu, J. S.},
title = {Markov Chain Monte Carlo and Related Topics},
institution = {Department of Statistics, Stanford University},
}
@TECHREPORT{MacPer:96,
author = {MacEachern, S. N. and Peruggia, M.},
title = {Subsampling the Gibbs Sampler: Variance Reduction},
institution = {Department of Statistics, The Ohio State University},
year = {1996},
}
@ARTICLE{Mac.B:94,
author = {MacEachern, S.N. and Berliner, L.M.},
title = {Subsampling the Gibbs sampler},
journal = {The American Statistician},
year = {1994},
volume = {48},
pages = {188-190},
}
@MANUAL{Splus:98,
title = {S-Plus: Version 4.5},
author = {MathSoft},
organization = {Data Analysis Products Division, MathSoft, Inc.},
address = {Seatle},
year = {1998},
}
@TECHREPORT{WWW,
author = {Mengersen, K.L. and Robert, C.P. and Guihenneuc-Jouyaux},
title = {MCMC convergence diagnostics: a Rclassification},
institution = {Laboratoire de Statistique, CREST, INSEE, Paris},
year = {1998},
number = {16},
}
@ARTICLE{Met:87,
author = {Metropolis, N.},
title = {The beginning of the Monte Carlo method},
journal = {Los Alamos Science},
year = {1987},
number = {Special issue},
pages = {125-130},
}
@ARTICLE{Met.R.R.T.T:53,
author = {Metropolis, N. and Rosenbluth, A.W. and Rosenbluth, M.N. and Teller, A.H. and Teller, E.},
title = {Equations of state calculations by fast computing machine},
journal = {J. Chem. Phys.},
year = {1953},
volume = {21},
pages = {1087-1091},
}
@ARTICLE{MirTie,
author = {Mira, A. and Tierney, L.},
title = {Efficiency and Convergence Properties of Slice Samplers},
journal = {Scand. J. Statist.},
year = {2002},
volume = {29},
pages = {1-12},
institution = {School of Statistics, University of Minnesota},
}
@ARTICLE{Nea:03,
author = {Neal, R. M.},
title = {Slice Sampling},
journal = {The Annals of Statistics},
year = {2003},
volume = {31},
number = {3},
pages = {705-767},
}
@ARTICLE{Nea:01,
author = {Neal, R. M.},
title = {Annealed importance sampling},
journal = {Statistics and Computing},
year = {2001},
volume = {11},
pages = {125-139},
}
@TECHREPORT{Nea:93,
author = {Neal, R. M.},
title = {Probabilistic Inference Using Markov Chain Monte Carlo Methods},
institution = {Department of Computer Science, University of Toronto},
year = {1993},
}
@ARTICLE{NeaSam:97,
author = {Neath, A. A. and Samaniego, F. J.},
title = {On the Efficacy of Bayesian Inference for Nonidentifiable Models},
journal = {The American Statistician},
year = {1997},
volume = {51},
number = {3},
pages = {225-232},
}
@MANUAL{Fbayes:96,
title = {First Bayes: Version 1.3},
author = {O'Hagan, A.},
organization = {Data Analysis Products Division, MathSoft, Inc.},
address = {Nottingham},
year = {1996},
}
@ARTICLE{PauPer:94,
author = {Paulino, C. D. M. and Pereira, C. A. B.},
title = {On Identifiability of Parametric Statistical Models},
journal = {Journal of the Italian Statistical Society},
year = {1994},
volume = {3},
number = {1},
pages = {125-151},
}
@ARTICLE{Pes:73,
author = {Peskun, P. H.},
title = {Optimum Monte-Carlo sampling using Markov chains},
journal = {Biometrika},
year = {1973},
volume = {60},
number = {3},
pages = {607},
}
@INPROCEEDINGS{Raf.L:92,
author = {Raftery, A.L. and Lewis, S.},
title = {How many iterations in the Gibbs sampler?},
booktitle = {Bayesian Statistics 4},
year = {1992},
editor = {Bernardo, J.M. and Berger,J.O. and Dawid, A.P. and Smith, A.F.M.},
pages = {763-774},
address = {Oxford},
publisher = {University Press},
}
@ARTICLE{Rit.T:92,
author = {Ritter, C. and Tanner, M.A.},
title = {Facilitating the Gibbs sampler: the Gibbs stopper and the Griddy-Gibbs sampler},
journal = {Journal of the American Statistical Association},
year = {1992},
volume = {87},
pages = {861-868},
}
@ARTICLE{Rob:92,
author = {Roberts, G. O.},
title = {Convergence Diagnostics of the Gibbs Sampler},
journal = {Bayesian Statistics},
year = {1992},
volume = {4},
pages = {775-782},
}
@ARTICLE{RobRos:99,
author = {Roberts, G. O. and Rosenthal, J. S.},
title = {Convergence of slice sampler Markov chains},
journal = {Journal of the Royal Statistical Society B},
year = {1999},
volume = {61},
pages = {643-660},
}
@ARTICLE{RobSmi:94,
author = {Roberts, G. O. and Smith, A. F. M.},
title = {Simple conditions for the convergence of the Gibbs sampler and Metropolis-Hastings algorithms},
journal = {Stochastic Processes and their Applications},
year = {1994},
volume = {49},
pages = {207-216},
}
@ARTICLE{Rob.P:94,
author = {Roberts, G.O. and Polson, N.G.},
title = {On the geometric convergence of the Gibbs sampler},
journal = {Journal of the Royal Statistical Society B},
year = {1994},
volume = {56},
pages = {377-384},
}
@ARTICLE{Smi.G:92,
author = {Smith, A.F.M. and Gelfand, A.E.},
title = {Bayesian statistics without tears: a sampling-resampling perspective},
journal = {The American Statistician},
year = {1992},
volume = {46},
pages = {84-88},
}
@ARTICLE{Smi.R:93,
author = {Smith, A.F.M. and Roberts, G.O.},
title = {Bayesian computation via the Gibbs sampler and related Markov chain Monte Carlo methods},
journal = {Journal of the Royal Statistical Society B},
year = {1993},
volume = {55},
pages = {3-23},
}
@MANUAL{BOA,
title = {Bayesian Output Analysis Program (BOA), Version 1.1 User's manual},
author = {Smith, B. J. },
year = {2004},
}
@TECHREPORT{Spi.B.C:98,
author = {Spiegelhalter, D. and Best, N. and Carlin, B.P.},
title = {Bayesian deviance, the effective number of parameters, and the comparison of arbitrarily complex models},
institution = {Division of Biostatiscs, University of Minneasota},
year = {1998},
number = {9},
}
@MANUAL{Winbugs:98,
title = {WinBUGS - Bayesian inference using Gibbs sampling for Windows: Version 1.1.1},
author = {Spiegelhalter, D. and Thomas, A. and Best, N.},
organization = {MRC Biostatistics Unit},
address = {Cambrigde},
year = {1998},
}
@MANUAL{Bugs:97,
title = {BUGS - Bayesian inference using Gibbs sampling: Version 0.6},
author = {Spiegelhalter, D. and Thomas, A. and Best, N. and Gilks, W.},
organization = {MRC Biostatistics Unit},
address = {Cambrigde},
year = {1997},
}
@ARTICLE{Spial:02,
author = {Spiegelhalter, D. J. and Best, N. G. and Carlin, B. P. and van der Linde, A.},
title = {Bayesian Measures of model complexity and fit},
journal = {Journal of the Royal Statistical Society B},
year = {2002},
number = {64},
pages = {583-639},
}
@MANUAL{Stata:97,
title = {Stata Statistical Software: Release 5.0},
author = {Stata-Corporation},
organization = {College Station, Stata Corporation},
address = {Texas},
year = {1997},
}
@UNPUBLISHED{Ste:03,
author = {Steinhaus, S.},
title = {Comparison of mathematical programs for data analysis},
year = {2003},
url = {http://www.scientificweb.com/ncrunch/ncrunch4.pdf},
}
@TECHREPORT{StrTwe:98,
author = {Stramer, O. and Tweedie, R. L.},
title = {Self-Targeting Candidates for Metropolis-Hastings Algorithms },
institution = {University of Iowa and Colorado State University },
year = {1998},
}
@ARTICLE{Tan.W:87,
author = {Tanner, M.A. and Wong, W.H.},
title = {The calculation of posterior distributions by data augmentation (with discussion)},
journal = {Journal of the American Statistical Association},
year = {1987},
volume = {82},
pages = {528-550},
}
@INPROCEEDINGS{Tho.S.G:92,
author = {Thomas, A. and Spiegelhalter, D.J. and Gilks, W.R.},
title = {BUGS: a program to perform Bayesian inference using Gibbs sampling},
booktitle = {Bayesian Statistics 4},
year = {1992},
editor = {Bernardo, J.M. and Berger, J.O. and Dawid, A.P. and Smith, A.F.M.},
pages = {837-842},
publisher = {Oxford University Press},
}
@ARTICLE{Tie:94,
author = {Tierney, L.},
title = {Markov chains for exploring posterior distributions},
journal = {The Annals of Statistics},
year = {1994},
volume = {22},
pages = {1701-1762},
}
@ARTICLE{TieMir:99,
author = {Tierney, L. and Mira, A.},
title = {Some Adaptive Monte Carlo Methods For Bayesian Inference},
journal = {Statistics in Medicine},
year = {1999},
number = {18},
pages = {2507-2515},
}
@ARTICLE{VanMen:01,
author = {Van Dyk, D. A. and Meng, X.},
title = {The Art of Data Augmentation},
journal = {Journal of the American Statistical Association},
year = {2001},
volume = {10},
number = {1},
pages = {1-50},
}
@ARTICLE{Wil.G:93,
author = {Wild, P. and Gilks, W.R.},
title = {Adaptive rejection sampling for log-concave density functions},
journal = {Applied Statistics},
year = {1993},
volume = {42},
pages = {701-709},
}
@BOOK{Wol:03,
title = {The Mathematica Book},
publisher = {Wolfram Media/Cambridge University Press},
year = {2003},
author = {Wolfram, S.},
edition = {Fifth},
}
@ARTICLE{Zel.M:95,
author = {Zellner, A. and Min, C.},
title = {Gibbs sampler convergence criteria},
journal = {Journal of the American Statistical Association},
year = {1995},
volume = {90},
pages = {921-927},
}
}}}
/***
|''Name:''|DataTiddlerPlugin|
|''Version:''|1.0.6 (2006-08-26)|
|''Source:''|http://tiddlywiki.abego-software.de/#DataTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Description
Enhance your tiddlers with structured data (such as strings, booleans, numbers, or even arrays and compound objects) that can be easily accessed and modified through named fields (in JavaScript code).
Such tiddler data can be used in various applications. E.g. you may create tables that collect data from various tiddlers.
''//Example: "Table with all December Expenses"//''
{{{
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
}}}
//(This assumes that expenses are stored in tiddlers tagged with "expense".)//
<<forEachTiddler
where
'tiddler.tags.contains("expense") && tiddler.data("month") == "Dec"'
write
'"|[["+tiddler.title+"]]|"+tiddler.data("descr")+"| "+tiddler.data("amount")+"|\n"'
>>
For other examples see DataTiddlerExamples.
''Access and Modify Tiddler Data''
You can "attach" data to every tiddler by assigning a JavaScript value (such as a string, boolean, number, or even arrays and compound objects) to named fields.
These values can be accessed and modified through the following Tiddler methods:
|!Method|!Example|!Description|
|{{{data(field)}}}|{{{t.data("age")}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{data(field,defaultValue)}}}|{{{t.data("isVIP",false)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{data()}}}|{{{t.data()}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{setData(field,value)}}}|{{{t.setData("age",42)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{setData(field,value,defaultValue)}}}|{{{t.setData("isVIP",flag,false)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
Alternatively you may use the following functions to access and modify the data. In this case the tiddler argument is either a tiddler or the name of a tiddler.
|!Method|!Description|
|{{{DataTiddler.getData(tiddler,field)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined {{{undefined}}} is returned.|
|{{{DataTiddler.getData(tiddler,field,defaultValue)}}}|Returns the value of the given data field of the tiddler. When no such field is defined or its value is undefined the defaultValue is returned.|
|{{{DataTiddler.getDataObject(tiddler)}}}|Returns the data object of the tiddler, with a property for every field. The properties of the returned data object may only be read and not be modified. To modify the data use DataTiddler.setData(...) or the corresponding Tiddler method.|
|{{{DataTiddler.setData(tiddler,field,value)}}}|Sets the value of the given data field of the tiddler to the value. When the value is {{{undefined}}} the field is removed.|
|{{{DataTiddler.setData(tiddler,field,value,defaultValue)}}}|Sets the value of the given data field of the tiddler to the value. When the value is equal to the defaultValue no value is set (and the field is removed).|
//(For details on the various functions see the detailed comments in the source code.)//
''Data Representation in a Tiddler''
The data of a tiddler is stored as plain text in the tiddler's content/text, inside a "data" section that is framed by a {{{<data>...</data>}}} block. Inside the data section the information is stored in the [[JSON format|http://www.crockford.com/JSON/index.html]].
//''Data Section Example:''//
{{{
<data>{"isVIP":true,"user":"John Brown","age":34}</data>
}}}
The data section is not displayed when viewing the tiddler (see also "The showData Macro").
Beside the data section a tiddler may have all kind of other content.
Typically you will not access the data section text directly but use the methods given above. Nevertheless you may retrieve the text of the data section's content through the {{{DataTiddler.getDataText(tiddler)}}} function.
''Saving Changes''
The "setData" methods respect the "ForceMinorUpdate" and "AutoSave" configuration values. I.e. when "ForceMinorUpdate" is true changing a value using setData will not affect the "modifier" and "modified" attributes. With "AutoSave" set to true every setData will directly save the changes after a setData.
''Notifications''
No notifications are sent when a tiddler's data value is changed through the "setData" methods.
''Escape Data Section''
In case that you want to use the text {{{<data>}}} or {{{</data>}}} in a tiddler text you must prefix the text with a tilde ('~'). Otherwise it may be wrongly considered as the data section. The tiddler text {{{~<data>}}} is displayed as {{{<data>}}}.
''The showData Macro''
By default the data of a tiddler (that is stored in the {{{<data>...</data>}}} section of the tiddler) is not displayed. If you want to display this data you may used the {{{<<showData ...>>}}} macro:
''Syntax:''
|>|{{{<<}}}''showData '' [''JSON''] [//tiddlerName//] {{{>>}}}|
|''JSON''|By default the data is rendered as a table with a "Name" and "Value" column. When defining ''JSON'' the data is rendered in JSON format|
|//tiddlerName//|Defines the tiddler holding the data to be displayed. When no tiddler is given the tiddler containing the showData macro is used. When the tiddler name contains spaces you must quote the name (or use the {{{[[...]]}}} syntax.)|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
!Revision history
* v1.0.6 (2006-08-26)
** Removed misleading comment
* v1.0.5 (2006-02-27) (Internal Release Only)
** Internal
*** Make "JSLint" conform
* v1.0.4 (2006-02-05)
** Bugfix: showData fails in TiddlyWiki 2.0
* v1.0.3 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.2 (2005-12-22)
** Enhancements:
*** Handle texts "<data>" or "</data>" more robust when used in a tiddler text or as a field value.
*** Improved (JSON) error messages.
** Bugs fixed:
*** References are not updated when using the DataTiddler.
*** Changes to compound objects are not always saved.
*** "~</data>" is not rendered correctly (expected "</data>")
* v1.0.1 (2005-12-13)
** Features:
*** The showData macro supports an optional "tiddlername" argument to specify the tiddler containing the data to be displayed
** Bugs fixed:
*** A script immediately following a data section is deleted when the data is changed. (Thanks to GeoffS for reporting.)
* v1.0.0 (2005-12-12)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// DataTiddlerPlugin
//============================================================================
//============================================================================
// Ensure that the DataTiddler Plugin is only installed once.
//
if (!version.extensions.DataTiddlerPlugin) {
version.extensions.DataTiddlerPlugin = {
major: 1, minor: 0, revision: 6,
date: new Date(2006, 7, 26),
type: 'plugin',
source: "http://tiddlywiki.abego-software.de/#DataTiddlerPlugin"
};
// For backward compatibility with v1.2.x
//
if (!window.story) window.story=window;
if (!TiddlyWiki.prototype.getTiddler) {
TiddlyWiki.prototype.getTiddler = function(title) {
var t = this.tiddlers[title];
return (t !== undefined && t instanceof Tiddler) ? t : null;
};
}
//============================================================================
// DataTiddler Class
//============================================================================
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
function DataTiddler() {
}
DataTiddler = {
// Function to stringify a JavaScript value, producing the text for the data section content.
// (Must match the implementation of DataTiddler.parse.)
//
stringify : null,
// Function to parse the text for the data section content, producing a JavaScript value.
// (Must match the implementation of DataTiddler.stringify.)
//
parse : null
};
// Ensure access for IE
window.DataTiddler = DataTiddler;
// ---------------------------------------------------------------------------
// Data Accessor and Mutator
// ---------------------------------------------------------------------------
// Returns the value of the given data field of the tiddler.
// When no such field is defined or its value is undefined
// the defaultValue is returned.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.getData = function(tiddler, field, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataValue(t, field, defaultValue);
};
// Sets the value of the given data field of the tiddler to
// the value. When the value is equal to the defaultValue
// no value is set (and the field is removed)
//
// Changing data of a tiddler will not trigger notifications.
//
// @param tiddler either a tiddler name or a tiddler
//
DataTiddler.setData = function(tiddler, field, value, defaultValue) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler+ "("+t+")";
}
DataTiddler.setTiddlerDataValue(t, field, value, defaultValue);
};
// Returns the data object of the tiddler, with a property for every field.
//
// The properties of the returned data object may only be read and
// not be modified. To modify the data use DataTiddler.setData(...)
// or the corresponding Tiddler method.
//
// If no data section is defined a new (empty) object is returned.
//
// @param tiddler either a tiddler name or a Tiddler
//
DataTiddler.getDataObject = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.getTiddlerDataObject(t);
};
// Returns the text of the content of the data section of the tiddler.
//
// When no data section is defined for the tiddler null is returned
//
// @param tiddler either a tiddler name or a Tiddler
// @return [may be null]
//
DataTiddler.getDataText = function(tiddler) {
var t = (typeof tiddler == "string") ? store.getTiddler(tiddler) : tiddler;
if (!(t instanceof Tiddler)) {
throw "Tiddler expected. Got "+tiddler;
}
return DataTiddler.readDataSectionText(t);
};
// ---------------------------------------------------------------------------
// Internal helper methods (must not be used by code from outside this plugin)
// ---------------------------------------------------------------------------
// Internal.
//
// The original JSONError is not very user friendly,
// especially it does not define a toString() method
// Therefore we extend it here.
//
DataTiddler.extendJSONError = function(ex) {
if (ex.name == 'JSONError') {
ex.toString = function() {
return ex.name + ": "+ex.message+" ("+ex.text+")";
};
}
return ex;
};
// Internal.
//
// @param t a Tiddler
//
DataTiddler.getTiddlerDataObject = function(t) {
if (t.dataObject === undefined) {
var data = DataTiddler.readData(t);
t.dataObject = (data) ? data : {};
}
return t.dataObject;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.getTiddlerDataValue = function(tiddler, field, defaultValue) {
var value = DataTiddler.getTiddlerDataObject(tiddler)[field];
return (value === undefined) ? defaultValue : value;
};
// Internal.
//
// @param tiddler a Tiddler
//
DataTiddler.setTiddlerDataValue = function(tiddler, field, value, defaultValue) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
var oldValue = data[field];
if (value == defaultValue) {
if (oldValue !== undefined) {
delete data[field];
DataTiddler.save(tiddler);
}
return;
}
data[field] = value;
DataTiddler.save(tiddler);
};
// Internal.
//
// Reads the data section from the tiddler's content and returns its text
// (as a String).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readDataSectionText = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
if (matches === null || !matches[2]) {
return null;
}
return matches[2];
};
// Internal.
//
// Reads the data section from the tiddler's content and returns it
// (as an internalized object).
//
// Returns null when no data is defined.
//
// @param tiddler a Tiddler
// @return [may be null]
//
DataTiddler.readData = function(tiddler) {
var text = DataTiddler.readDataSectionText(tiddler);
try {
return text ? DataTiddler.parse(text) : null;
} catch(ex) {
throw DataTiddler.extendJSONError(ex);
}
};
// Internal.
//
// Returns the serialized text of the data of the given tiddler, as it
// should be stored in the data section.
//
// @param tiddler a Tiddler
//
DataTiddler.getDataTextOfTiddler = function(tiddler) {
var data = DataTiddler.getTiddlerDataObject(tiddler);
return DataTiddler.stringify(data);
};
// Internal.
//
DataTiddler.indexOfNonEscapedText = function(s, subString, startIndex) {
var index = s.indexOf(subString, startIndex);
while ((index > 0) && (s[index-1] == '~')) {
index = s.indexOf(subString, index+1);
}
return index;
};
// Internal.
//
DataTiddler.getDataSectionInfo = function(text) {
// Special care must be taken to handle "<data>" and "</data>" texts inside
// a data section.
// Also take care not to use an escaped <data> (i.e. "~<data>") as the start
// of a data section. (Same for </data>)
// NOTE: we are explicitly searching for a data section that contains a JSON
// string, i.e. framed with braces. This way we are little bit more robust in
// case the tiddler contains unescaped texts "<data>" or "</data>". This must
// be changed when using a different stringifier.
var startTagText = "<data>{";
var endTagText = "}</data>";
var startPos = 0;
// Find the first not escaped "<data>".
var startDataTagIndex = DataTiddler.indexOfNonEscapedText(text, startTagText, 0);
if (startDataTagIndex < 0) {
return null;
}
// Find the *last* not escaped "</data>".
var endDataTagIndex = text.indexOf(endTagText, startDataTagIndex);
if (endDataTagIndex < 0) {
return null;
}
var nextEndDataTagIndex;
while ((nextEndDataTagIndex = text.indexOf(endTagText, endDataTagIndex+1)) >= 0) {
endDataTagIndex = nextEndDataTagIndex;
}
return {
prefixEnd: startDataTagIndex,
dataStart: startDataTagIndex+(startTagText.length)-1,
dataEnd: endDataTagIndex,
suffixStart: endDataTagIndex+(endTagText.length)
};
};
// Internal.
//
// Returns the "matches" of a content of a DataTiddler on the
// "data" regular expression. Return null when no data is defined
// in the tiddler content.
//
// Group 1: text before data section (prefix)
// Group 2: content of data section
// Group 3: text behind data section (suffix)
//
// @param tiddler a Tiddler
// @return [may be null] null when the tiddler contains no data section, otherwise see above.
//
DataTiddler.getDataTiddlerMatches = function(tiddler) {
var text = tiddler.text;
var info = DataTiddler.getDataSectionInfo(text);
if (!info) {
return null;
}
var prefix = text.substr(0,info.prefixEnd);
var data = text.substr(info.dataStart, info.dataEnd-info.dataStart+1);
var suffix = text.substr(info.suffixStart);
return [text, prefix, data, suffix];
};
// Internal.
//
// Saves the data in a <data> block of the given tiddler (as a minor change).
//
// The "chkAutoSave" and "chkForceMinorUpdate" options are respected.
// I.e. the TiddlyWiki *file* is only saved when AutoSave is on.
//
// Notifications are not send.
//
// This method should only be called when the data really has changed.
//
// @param tiddler
// the tiddler to be saved.
//
DataTiddler.save = function(tiddler) {
var matches = DataTiddler.getDataTiddlerMatches(tiddler);
var prefix;
var suffix;
if (matches === null) {
prefix = tiddler.text;
suffix = "";
} else {
prefix = matches[1];
suffix = matches[3];
}
var dataText = DataTiddler.getDataTextOfTiddler(tiddler);
var newText =
(dataText !== null)
? prefix + "<data>" + dataText + "</data>" + suffix
: prefix + suffix;
if (newText != tiddler.text) {
// make the change in the tiddlers text
// ... see DataTiddler.MyTiddlerChangedFunction
tiddler.isDataTiddlerChange = true;
// ... do the action change
tiddler.set(
tiddler.title,
newText,
config.options.txtUserName,
config.options.chkForceMinorUpdate? undefined : new Date(),
tiddler.tags);
// ... see DataTiddler.MyTiddlerChangedFunction
delete tiddler.isDataTiddlerChange;
// Mark the store as dirty.
store.dirty = true;
// AutoSave if option is selected
if(config.options.chkAutoSave) {
saveChanges();
}
}
};
// Internal.
//
DataTiddler.MyTiddlerChangedFunction = function() {
// Remove the data object from the tiddler when the tiddler is changed
// by code other than DataTiddler code.
//
// This is necessary since the data object is just a "cached version"
// of the data defined in the data section of the tiddler and the
// "external" change may have changed the content of the data section.
// Thus we are not sure if the data object reflects the data section
// contents.
//
// By deleting the data object we ensure that the data object is
// reconstructed the next time it is needed, with the data defined by
// the data section in the tiddler's text.
// To indicate that a change is a "DataTiddler change" a temporary
// property "isDataTiddlerChange" is added to the tiddler.
if (this.dataObject && !this.isDataTiddlerChange) {
delete this.dataObject;
}
// call the original code.
DataTiddler.originalTiddlerChangedFunction.apply(this, arguments);
};
//============================================================================
// Formatters
//============================================================================
// This formatter ensures that "~<data>" is rendered as "<data>". This is used to
// escape the "<data>" of a data section, just in case someone really wants to use
// "<data>" as a text in a tiddler and not start a data section.
//
// Same for </data>.
//
config.formatters.push( {
name: "data-escape",
match: "~<\\/?data>",
handler: function(w) {
w.outputText(w.output,w.matchStart + 1,w.nextMatch);
}
} );
// This formatter ensures that <data>...</data> sections are not rendered.
//
config.formatters.push( {
name: "data",
match: "<data>",
handler: function(w) {
var info = DataTiddler.getDataSectionInfo(w.source);
if (info && info.prefixEnd == w.matchStart) {
w.nextMatch = info.suffixStart;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
} );
//============================================================================
// Tiddler Class Extension
//============================================================================
// "Hijack" the changed method ---------------------------------------------------
DataTiddler.originalTiddlerChangedFunction = Tiddler.prototype.changed;
Tiddler.prototype.changed = DataTiddler.MyTiddlerChangedFunction;
// Define accessor methods -------------------------------------------------------
// Returns the value of the given data field of the tiddler. When no such field
// is defined or its value is undefined the defaultValue is returned.
//
// When field is undefined (or null) the data object is returned. (See
// DataTiddler.getDataObject.)
//
// @param field [may be null, undefined]
// @param defaultValue [may be null, undefined]
// @return [may be null, undefined]
//
Tiddler.prototype.data = function(field, defaultValue) {
return (field)
? DataTiddler.getTiddlerDataValue(this, field, defaultValue)
: DataTiddler.getTiddlerDataObject(this);
};
// Sets the value of the given data field of the tiddler to the value. When the
// value is equal to the defaultValue no value is set (and the field is removed).
//
// @param value [may be null, undefined]
// @param defaultValue [may be null, undefined]
//
Tiddler.prototype.setData = function(field, value, defaultValue) {
DataTiddler.setTiddlerDataValue(this, field, value, defaultValue);
};
//============================================================================
// showData Macro
//============================================================================
config.macros.showData = {
// Standard Properties
label: "showData",
prompt: "Display the values stored in the data section of the tiddler"
};
config.macros.showData.handler = function(place,macroName,params) {
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the optional "JSON"
var showInJSONFormat = false;
if ((i < params.length) && params[i] == "JSON") {
i++;
showInJSONFormat = true;
}
var tiddlerName = story.findContainingTiddler(place).id.substr(7);
if (i < params.length) {
tiddlerName = params[i];
i++;
}
// --- Processing ------------------------------------------
try {
if (showInJSONFormat) {
this.renderDataInJSONFormat(place, tiddlerName);
} else {
this.renderDataAsTable(place, tiddlerName);
}
} catch (e) {
this.createErrorElement(place, e);
}
};
config.macros.showData.renderDataInJSONFormat = function(place,tiddlerName) {
var text = DataTiddler.getDataText(tiddlerName);
if (text) {
createTiddlyElement(place,"pre",null,null,text);
}
};
config.macros.showData.renderDataAsTable = function(place,tiddlerName) {
var text = "|!Name|!Value|\n";
var data = DataTiddler.getDataObject(tiddlerName);
if (data) {
for (var i in data) {
var value = data[i];
text += "|"+i+"|"+DataTiddler.stringify(value)+"|\n";
}
}
wikify(text, place);
};
// Internal.
//
// Creates an element that holds an error message
//
config.macros.showData.createErrorElement = function(place, exception) {
var message = (exception.description) ? exception.description : exception.toString();
return createTiddlyElement(place,"span",null,"showDataError","<<showData ...>>: "+message);
};
// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
".showDataError{color: #ffffff;background-color: #880000;}",
"showData");
} // of "install only once"
// Used Globals (for JSLint) ==============
// ... TiddlyWiki Core
/*global createTiddlyElement, saveChanges, store, story, wikify */
// ... DataTiddler
/*global DataTiddler */
// ... JSON
/*global JSON */
/***
!JSON Code, used to serialize the data
***/
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
The global object JSON contains two methods.
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
The value must not be cyclical.
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
throw a 'JSONError' exception if there is an error.
*/
var JSON = {
copyright: '(c)2005 JSON.org',
license: 'http://www.crockford.com/JSON/license.html',
/*
Stringify a JavaScript value, producing a JSON text.
*/
stringify: function (v) {
var a = [];
/*
Emit a string.
*/
function e(s) {
a[a.length] = s;
}
/*
Convert a value.
*/
function g(x) {
var c, i, l, v;
switch (typeof x) {
case 'object':
if (x) {
if (x instanceof Array) {
e('[');
l = a.length;
for (i = 0; i < x.length; i += 1) {
v = x[i];
if (typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(v);
}
}
e(']');
return;
} else if (typeof x.toString != 'undefined') {
e('{');
l = a.length;
for (i in x) {
v = x[i];
if (x.hasOwnProperty(i) &&
typeof v != 'undefined' &&
typeof v != 'function') {
if (l < a.length) {
e(',');
}
g(i);
e(':');
g(v);
}
}
return e('}');
}
}
e('null');
return;
case 'number':
e(isFinite(x) ? +x : 'null');
return;
case 'string':
l = x.length;
e('"');
for (i = 0; i < l; i += 1) {
c = x.charAt(i);
if (c >= ' ') {
if (c == '\\' || c == '"') {
e('\\');
}
e(c);
} else {
switch (c) {
case '\b':
e('\\b');
break;
case '\f':
e('\\f');
break;
case '\n':
e('\\n');
break;
case '\r':
e('\\r');
break;
case '\t':
e('\\t');
break;
default:
c = c.charCodeAt();
e('\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16));
}
}
}
e('"');
return;
case 'boolean':
e(String(x));
return;
default:
e('null');
return;
}
}
g(v);
return a.join('');
},
/*
Parse a JSON text, producing a JavaScript value.
*/
parse: function (text) {
var p = /^\s*(([,:{}\[\]])|"(\\.|[^\x00-\x1f"\\])*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)\s*/,
token,
operator;
function error(m, t) {
throw {
name: 'JSONError',
message: m,
text: t || operator || token
};
}
function next(b) {
if (b && b != operator) {
error("Expected '" + b + "'");
}
if (text) {
var t = p.exec(text);
if (t) {
if (t[2]) {
token = null;
operator = t[2];
} else {
operator = null;
try {
token = eval(t[1]);
} catch (e) {
error("Bad token", t[1]);
}
}
text = text.substring(t[0].length);
} else {
error("Unrecognized token", text);
}
} else {
token = operator = undefined;
}
}
function val() {
var k, o;
switch (operator) {
case '{':
next('{');
o = {};
if (operator != '}') {
for (;;) {
if (operator || typeof token != 'string') {
error("Missing key");
}
k = token;
next();
next(':');
o[k] = val();
if (operator != ',') {
break;
}
next(',');
}
}
next('}');
return o;
case '[':
next('[');
o = [];
if (operator != ']') {
for (;;) {
o.push(val());
if (operator != ',') {
break;
}
next(',');
}
}
next(']');
return o;
default:
if (operator !== null) {
error("Missing value");
}
k = token;
next();
return k;
}
}
next();
return val();
}
};
/***
!Setup the data serialization
***/
DataTiddler.format = "JSON";
DataTiddler.stringify = JSON.stringify;
DataTiddler.parse = JSON.parse;
//}}}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|© 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description
Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.
''Syntax:''
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]] is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].
!Revision history
* v1.0.8 (2007-04-12)
** Adapted to latest TiddlyWiki 2.2 Beta importTiddlyWiki API (introduced with changeset 2004). TiddlyWiki 2.2 Beta builds prior to changeset 2004 are no longer supported (but TiddlyWiki 2.1 and earlier, of cause)
* v1.0.7 (2007-03-28)
** Also support "pre" formatted TiddlyWikis (introduced with TW 2.2) (when using "in" clause to work on external tiddlers)
* v1.0.6 (2006-09-16)
** Context provides "viewerTiddler", i.e. the tiddler used to view the macro. Most times this is equal to the "inTiddler", but when using the "tiddler" macro both may be different.
** Support "begin", "end" and "none" expressions in "write" action
* v1.0.5 (2006-02-05)
** Pass tiddler containing the macro with wikify, context object also holds reference to tiddler containing the macro ("inTiddler"). Thanks to SimonBaird.
** Support Firefox 1.5.0.1
** Internal
*** Make "JSLint" conform
*** "Only install once"
* v1.0.4 (2006-01-06)
** Support TiddlyWiki 2.0
* v1.0.3 (2005-12-22)
** Features:
*** Write output to a file supports multi-byte environments (Thanks to Bram Chen)
*** Provide API to access the forEachTiddler functionality directly through JavaScript (see getTiddlers and performMacro)
** Enhancements:
*** Improved error messages on InternetExplorer.
* v1.0.2 (2005-12-10)
** Features:
*** context object also holds reference to store (TiddlyWiki)
** Fixed Bugs:
*** ForEachTiddler 1.0.1 has broken support on win32 Opera 8.51 (Thanks to BrunoSabin for reporting)
* v1.0.1 (2005-12-08)
** Features:
*** Access tiddlers stored in separated TiddlyWikis through the "in" option. I.e. you are no longer limited to only work on the "current TiddlyWiki".
*** Write output to an external file using the "toFile" option of the "write" action. With this option you may write your customized tiddler exports.
*** Use the "script" section to define "helper" JavaScript functions etc. to be used in the various JavaScript expressions (whereClause, sortClause, action arguments,...).
*** Access and store context information for the current forEachTiddler invocation (through the build-in "context" object) .
*** Improved script evaluation (for where/sort clause and write scripts).
* v1.0.0 (2005-11-20)
** initial version
!Code
***/
//{{{
//============================================================================
//============================================================================
// ForEachTiddlerPlugin
//============================================================================
//============================================================================
// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {
if (!window.abego) window.abego = {};
version.extensions.ForEachTiddlerPlugin = {
major: 1, minor: 0, revision: 8,
date: new Date(2007,3,12),
source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};
// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
TiddlyWiki.prototype.forEachTiddler = function(callback) {
for(var t in this.tiddlers) {
callback.call(this,t,this.tiddlers[t]);
}
};
}
//============================================================================
// forEachTiddler Macro
//============================================================================
version.extensions.forEachTiddler = {
major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};
// ---------------------------------------------------------------------------
// Configurations and constants
// ---------------------------------------------------------------------------
config.macros.forEachTiddler = {
// Standard Properties
label: "forEachTiddler",
prompt: "Perform actions on a (sorted) selection of tiddlers",
// actions
actions: {
addToList: {},
write: {}
}
};
// ---------------------------------------------------------------------------
// The forEachTiddler Macro Handler
// ---------------------------------------------------------------------------
config.macros.forEachTiddler.getContainingTiddler = function(e) {
while(e && !hasClass(e,"tiddler"))
e = e.parentNode;
var title = e ? e.getAttribute("tiddler") : null;
return title ? store.getTiddler(title) : null;
};
config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);
if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
// --- Parsing ------------------------------------------
var i = 0; // index running over the params
// Parse the "in" clause
var tiddlyWikiPath = undefined;
if ((i < params.length) && params[i] == "in") {
i++;
if (i >= params.length) {
this.handleError(place, "TiddlyWiki path expected behind 'in'.");
return;
}
tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the where clause
var whereClause ="true";
if ((i < params.length) && params[i] == "where") {
i++;
whereClause = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the sort stuff
var sortClause = null;
var sortAscending = true;
if ((i < params.length) && params[i] == "sortBy") {
i++;
if (i >= params.length) {
this.handleError(place, "sortClause missing behind 'sortBy'.");
return;
}
sortClause = this.paramEncode(params[i]);
i++;
if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
sortAscending = params[i] == "ascending";
i++;
}
}
// Parse the script
var scriptText = null;
if ((i < params.length) && params[i] == "script") {
i++;
scriptText = this.paramEncode((i < params.length) ? params[i] : "");
i++;
}
// Parse the action.
// When we are already at the end use the default action
var actionName = "addToList";
if (i < params.length) {
if (!config.macros.forEachTiddler.actions[params[i]]) {
this.handleError(place, "Unknown action '"+params[i]+"'.");
return;
} else {
actionName = params[i];
i++;
}
}
// Get the action parameter
// (the parsing is done inside the individual action implementation.)
var actionParameter = params.slice(i);
// --- Processing ------------------------------------------
try {
this.performMacro({
place: place,
inTiddler: tiddler,
whereClause: whereClause,
sortClause: sortClause,
sortAscending: sortAscending,
actionName: actionName,
actionParameter: actionParameter,
scriptText: scriptText,
tiddlyWikiPath: tiddlyWikiPath});
} catch (e) {
this.handleError(place, e);
}
};
// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {
var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);
var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
context["tiddlyWiki"] = tiddlyWiki;
// Get the tiddlers, as defined by the whereClause
var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
context["tiddlers"] = tiddlers;
// Sort the tiddlers, when sorting is required.
if (parameter.sortClause) {
this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
}
return {tiddlers: tiddlers, context: context};
};
// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
return this.getTiddlersAndContext(parameter).tiddlers;
};
// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
// The following properties are supported:
//
// place
// whereClause
// sortClause
// sortAscending
// actionName
// actionParameter
// scriptText
// tiddlyWikiPath
//
// All properties are optional.
// For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
var tiddlersAndContext = this.getTiddlersAndContext(parameter);
// Perform the action
var actionName = parameter.actionName ? parameter.actionName : "addToList";
var action = config.macros.forEachTiddler.actions[actionName];
if (!action) {
this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
return;
}
var actionHandler = action.handler;
actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};
// ---------------------------------------------------------------------------
// The actions
// ---------------------------------------------------------------------------
// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
return;
}
// Perform the action.
var list = document.createElement("ul");
place.appendChild(list);
for (var i = 0; i < tiddlers.length; i++) {
var tiddler = tiddlers[i];
var listItem = document.createElement("li");
list.appendChild(listItem);
createTiddlyLink(listItem, tiddler.title, true);
}
};
abego.parseNamedParameter = function(name, parameter, i) {
var beginExpression = null;
if ((i < parameter.length) && parameter[i] == name) {
i++;
if (i >= parameter.length) {
throw "Missing text behind '%0'".format([name]);
}
return config.macros.forEachTiddler.paramEncode(parameter[i]);
}
return null;
}
// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
// Parse the parameter
var p = 0;
if (p >= parameter.length) {
this.handleError(place, "Missing expression behind 'write'.");
return;
}
var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
// Parse the "begin" option
var beginExpression = abego.parseNamedParameter("begin", parameter, p);
if (beginExpression !== null)
p += 2;
var endExpression = abego.parseNamedParameter("end", parameter, p);
if (endExpression !== null)
p += 2;
var noneExpression = abego.parseNamedParameter("none", parameter, p);
if (noneExpression !== null)
p += 2;
// Parse the "toFile" option
var filename = null;
var lineSeparator = undefined;
if ((p < parameter.length) && parameter[p] == "toFile") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
return;
}
filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
p++;
if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
p++;
if (p >= parameter.length) {
this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
return;
}
lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
p++;
}
}
// Check for extra parameters
if (parameter.length > p) {
config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
return;
}
// Perform the action.
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
var count = tiddlers.length;
var text = "";
if (count > 0 && beginExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
for (var i = 0; i < count; i++) {
var tiddler = tiddlers[i];
text += func(tiddler, context, count, i);
}
if (count > 0 && endExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);
if (count == 0 && noneExpression)
text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
if (filename) {
if (lineSeparator !== undefined) {
lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
text = text.replace(/\n/mg,lineSeparator);
}
saveFile(filename, convertUnicodeToUTF8(text));
} else {
var wrapper = createTiddlyElement(place, "span");
wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
}
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
return {
place : placeParam,
whereClause : whereClauseParam,
sortClause : sortClauseParam,
sortAscending : sortAscendingParam,
script : scriptText,
actionName : actionNameParam,
actionParameter : actionParameterParam,
tiddlyWikiPath : tiddlyWikiPathParam,
inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
};
};
// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
if (!idPrefix) {
idPrefix = "store";
}
var lenPrefix = idPrefix.length;
// Read the content of the given file
var content = loadFile(this.getLocalPath(path));
if(content === null) {
throw "TiddlyWiki '"+path+"' not found.";
}
var tiddlyWiki = new TiddlyWiki();
// Starting with TW 2.2 there is a helper function to import the tiddlers
if (tiddlyWiki.importTiddlyWiki) {
if (!tiddlyWiki.importTiddlyWiki(content))
throw "File '"+path+"' is not a TiddlyWiki.";
tiddlyWiki.dirty = false;
return tiddlyWiki;
}
// The legacy code, for TW < 2.2
// Locate the storeArea div's
var posOpeningDiv = content.indexOf(startSaveArea);
var posClosingDiv = content.lastIndexOf(endSaveArea);
if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
throw "File '"+path+"' is not a TiddlyWiki.";
}
var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
// Create a "div" element that contains the storage text
var myStorageDiv = document.createElement("div");
myStorageDiv.innerHTML = storageText;
myStorageDiv.normalize();
// Create all tiddlers in a new TiddlyWiki
// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
var store = myStorageDiv.childNodes;
for(var t = 0; t < store.length; t++) {
var e = store[t];
var title = null;
if(e.getAttribute)
title = e.getAttribute("tiddler");
if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
title = e.id.substr(lenPrefix);
if(title && title !== "") {
var tiddler = tiddlyWiki.createTiddler(title);
tiddler.loadFromDiv(e,title);
}
}
tiddlyWiki.dirty = false;
return tiddlyWiki;
};
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
//
// (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
var script = context["script"];
var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
var fullText = (script ? script+";" : "")+functionText+";theFunction;";
return eval(fullText);
};
// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
var result = [];
var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
tiddlyWiki.forEachTiddler(function(title,tiddler) {
if (func(tiddler, context, undefined, undefined)) {
result.push(tiddler);
}
});
return result;
};
// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
var message = "Extra parameter behind '"+actionName+"':";
for (var i = firstUnusedIndex; i < parameter.length; i++) {
message += " "+parameter[i];
}
this.handleError(place, mess