Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
/***
|Name|AdvancedOptionsPlugin|
|Source|http://www.TiddlyTools.com/#AdvancedOptionsPlugin|
|Documentation|http://www.TiddlyTools.com/#AdvancedOptionsPlugin|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.3|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|automatically add plugin-defined options to the [[AdvancedOptions]] shadow tiddler|
!!!!!Usage
<<<
At document startup, this plugin examines each tiddler tagged with <<tag systemConfig>> and looks for a tiddler slice named "Options" whose value refers to a tiddler section (or separate tiddler) that contains an 'advanced options control panel' for configuring that plugin's features and behavior. For each plugin that contains an "Options" slice, a tabbed entry is automatically created in the [[AdvancedOptions]] shadow tiddler to display that plugin's control panel.
As an optional fallback for backward-compatibility with plugin tiddlers that do not define the "Options" slice, this plugin will also look for a section heading named "Configuration" within those tiddlers, so that older plugins that define this section can automatically have their settings added to the [[AdvancedOptions]] tiddler without requiring the "Options" slice to be added.
<<<
!!!!!Configuration
<<<
<<option chkAdvancedOptions>> automatically add plugin-defined options to the [[AdvancedOptions]] shadow tiddler
<<option chkAdvancedOptionsBackstage>> automatically add plugin-defined options to Backstage menu
<<option chkAdvancedOptionsFallback>> use <<option txtAdvancedOptionsFallback>> section as a fallback for plugins that don't define an ~AdvancedOptions slice
//note: these settings only take effect after reloading the document//
<<<
!!!!!Revisions
<<<
2008.05.09 [1.1.0] add "options" panel to backstage
2008.04.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.AdvancedOptionsPlugin= {major: 1, minor: 1, revision: 0, date: new Date(2008,5,9)};
if (config.options.chkAdvancedOptions===undefined)
config.options.chkAdvancedOptions=true;
if (config.options.chkAdvancedOptionsBackstage===undefined)
config.options.chkAdvancedOptionsBackstage=true;
if (config.options.chkAdvancedOptionsFallback===undefined)
config.options.chkAdvancedOptionsFallback=true;
if (config.options.txtAdvancedOptionsFallback===undefined)
config.options.txtAdvancedOptionsFallback="Configuration";
if (config.optionsDesc) config.optionsDesc.chkAdvancedOptions=
"automatically add plugin-defined options to [[AdvancedOptions]]";
var items=[];
var fmt="[[%0 ]] [[view options for %0]] [[%1]]\n";
var section=config.options.txtAdvancedOptionsFallback;
var plugins=store.getTaggedTiddlers("systemConfig");
for (var p=0; p<plugins.length; p++) {
var tid=plugins[p].title;
var settings=store.getTiddlerSlice(tid,"Options");
if (!settings && config.options.chkAdvancedOptionsFallback && store.getTiddlerText(tid+"##"+section))
settings="##"+section; // fallback handling for older plugins
if (settings&&settings.length) {
if (settings.substr(0,2)=="##") settings=tid+settings;
items.push(fmt.format([tid,settings]));
}
}
if (items.length) config.shadowTiddlers.PluginOptions=
"!![[Plugin-defined options|PluginManager]]\n>@@text-align:left;<<tabs '' \n"+items.join(' ')+">>@@";
if (config.options.chkAdvancedOptions)
config.shadowTiddlers.AdvancedOptions+="{{smallform{{{wrap{<<tiddler PluginOptions>>}}}}}}";
// add "options" backstage task
if (config.tasks && config.options.chkAdvancedOptionsBackstage) { // for TW2.2b3 or above
config.tasks.options = {
text: "options",
tooltip: "manage plugin-defined option settings",
content: "{{smallform{{{groupbox{{{wrap{<<tiddler PluginOptions>>}}}}}}\n{{groupbox small {<<options>>}}}}}}"
}
config.backstageTasks.splice(config.backstageTasks.indexOf("plugins")+1,0,"options");
}
//}}}
/***
|Name|BreadcrumbsPlugin|
|Author|Eric Shulman|
|Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|
|Documentation|http://www.TiddlyTools.com/#BreadcrumbsPluginInfo|
|Version|2.0.0|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler,TiddlyWiki.prototype.deleteTiddler|
|Options|##Configuration|
|Description|list/jump to tiddlers viewed during this session plus "back" button/macro|
This plugin provides a list of links to all tiddlers opened during the session, creating a "trail of breadcrumbs" from one tiddler to the next, allowing you to quickly navigate to any previously viewed tiddler, or select 'home' to reset the display to the initial set of tiddlers that were open at the start of the session (i.e., when the document was loaded into the browser).
!!!!!Documentation
<<<
see [[BreadcrumbsPluginInfo]]
<<<
!!!!!Configuration
<<<
<<option chkCreateDefaultBreadcrumbs>> automatically create breadcrumbs display (if needed)
<<option chkShowBreadcrumbs>> show/hide breadcrumbs display
<<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler
<<option chkBreadcrumbsHideHomeLink>> omit 'Home' link from breadcrumbs display
<<option chkShowStartupBreadcrumbs>> show breadcrumbs for 'startup' tiddlers
<<option chkBreadcrumbsReverse>> show breadcrumbs in reverse order (most recent first)
<<option chkBreadcrumbsLimit>> limit breadcrumbs display to {{twochar{<<option txtBreadcrumbsLimit>>}}} items
<<option chkBreadcrumbsLimitOpenTiddlers>> limit open tiddlers to {{twochar{<<option txtBreadcrumbsLimitOpenTiddlers>>}}} items
<<<
!!!!!Revisions
<<<
2008.05.01 [2.0.0] added 'limit open tiddlers' feature (with safety check for tiddler in edit mode)
| Please see [[BreadcrumbsPluginInfo]] for previous revision details |
2006.02.01 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.BreadcrumbsPlugin= {major: 2, minor: 0, revision: 0, date: new Date("May 1, 2008")};
var co=config.options; // abbreviation
// show/hide display option (default is to SHOW breadcrumbs)
if (co.chkShowBreadcrumbs===undefined) co.chkShowBreadcrumbs=true;
// REORDER breadcrumbs when visiting previously viewed tiddler (default)
if (co.chkReorderBreadcrumbs===undefined) co.chkReorderBreadcrumbs=true;
// create default breadcrumbs display as needed (default is to CREATE)
if (co.chkCreateDefaultBreadcrumbs===undefined) co.chkCreateDefaultBreadcrumbs=true;
// show breadcrumbs for 'startup' tiddlers (default is FALSE = only show crumbs for tiddlers opened after startup)
if (co.chkShowStartupBreadcrumbs===undefined) co.chkShowStartupBreadcrumbs=false;
// show crumbs in reverse order (most recent first)
if (co.chkBreadcrumbsReverse===undefined) co.chkBreadcrumbsReverse=false;
// limit number of crumbs displayed
if (co.chkBreadcrumbsLimit===undefined) co.chkBreadcrumbsLimit=false;
if (co.txtBreadcrumbsLimit===undefined) co.txtBreadcrumbsLimit=5;
// limit number of open tiddlers
if (co.chkBreadcrumbsLimitOpenTiddlers===undefined) co.chkBreadcrumbsLimitOpenTiddlers=false;
if (co.txtBreadcrumbsLimitOpenTiddlers===undefined) co.txtBreadcrumbsLimitOpenTiddlers=3;
// omit home link from breadcrumbs display
if (co.chkBreadcrumbsHideHomeLink===undefined) co.chkBreadcrumbsHideHomeLink=false;
config.macros.breadcrumbs = {
crumbs: [], // the list of current breadcrumbs
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var area=createTiddlyElement(place,"span",null,"breadCrumbs",null);
area.setAttribute("homeSep",params[0]?params[0]:this.homeSeparator); // custom home separator
area.setAttribute("crumbSep",params[1]?params[1]:this.crumbSeparator); // custom crumb separator
this.render(area);
},
add: function (title) {
var thisCrumb = title;
var ind = this.crumbs.indexOf(thisCrumb);
if(ind === -1)
this.crumbs.push(thisCrumb);
else if (config.options.chkReorderBreadcrumbs)
this.crumbs.push(this.crumbs.splice(ind,1)[0]); // reorder crumbs
else
this.crumbs=this.crumbs.slice(0,ind+1); // trim crumbs
if (config.options.chkBreadcrumbsLimitOpenTiddlers)
this.limitOpenTiddlers();
this.refresh();
return false;
},
getAreas: function() {
var crumbAreas=[];
// find all DIVs with classname=="breadCrumbs"
// Note: use try/catch to avoid "Bad NPObject as private data" fatal error caused when
// some versions of embedded QuickTime player element is accessed by hasClass() function.
var all=document.getElementsByTagName("*");
for (var i=0; i<all.length; i++)
try{ if (hasClass(all[i],"breadCrumbs")) crumbAreas.push(all[i]); } catch(e) {;}
// find single DIV w/fixed ID (backward compatibility)
var byID=document.getElementById("breadCrumbs")
if (byID && !hasClass(byID,"breadCrumbs")) crumbAreas.push(byID);
if (!crumbAreas.length && config.options.chkCreateDefaultBreadcrumbs) {
// no existing crumbs display areas... create one...
var defaultArea = createTiddlyElement(null,"span",null,"breadCrumbs",null);
defaultArea.style.display= "none";
var targetArea= document.getElementById("tiddlerDisplay");
targetArea.parentNode.insertBefore(defaultArea,targetArea);
crumbAreas.push(defaultArea);
}
return crumbAreas;
},
refresh: function() {
var crumbAreas=this.getAreas();
for (var i=0; i<crumbAreas.length; i++) {
crumbAreas[i].style.display = config.options.chkShowBreadcrumbs?"block":"none";
removeChildren(crumbAreas[i]);
this.render(crumbAreas[i]);
}
},
render: function(here) {
var out=""
var homeSep=here.getAttribute("homeSep"); if (!homeSep) homeSep=this.homeSeparator;
var crumbSep=here.getAttribute("crumbSep"); if (!crumbSep) crumbSep=this.crumbSeparator;
if (!config.options.chkBreadcrumbsHideHomeLink) {
createTiddlyButton(here,"Home",null,this.home,"tiddlyLink tiddlyLinkExisting");
out+=homeSep;
}
for (c=0; c<this.crumbs.length; c++) // remove non-existing tiddlers from crumbs
if (!store.tiddlerExists(this.crumbs[c]) && !store.isShadowTiddler(this.crumbs[c]))
this.crumbs.splice(c,1);
var count=this.crumbs.length;
if (config.options.chkBreadcrumbsLimit && config.options.txtBreadcrumbsLimit<count)
count=config.options.txtBreadcrumbsLimit;
var list=[];
for (c=this.crumbs.length-count; c<this.crumbs.length; c++) list.push('[['+this.crumbs[c]+']]');
if (config.options.chkBreadcrumbsReverse) list.reverse();
out+=list.join(crumbSep);
wikify(out,here);
},
home: function() {
story.closeAllTiddlers();
restart();
config.macros.breadcrumbs.crumbs = [];
var crumbAreas=config.macros.breadcrumbs.getAreas();
for (var i=0; i<crumbAreas.length; i++) crumbAreas[i].style.display = "none";
return false;
},
limitOpenTiddlers: function() {
var limit=config.options.txtBreadcrumbsLimitOpenTiddlers; if (limit<1) limit=1;
for (c=this.crumbs.length-1; c>=0; c--) {
var tid=this.crumbs[c];
var elem=document.getElementById(story.idPrefix+tid);
if (elem) { // tiddler is displayed
if (limit <=0) { // display limit has been reached
if (elem.getAttribute("dirty")=="true") { // tiddler is being edited
var msg="'"+tid+"' is currently being edited.\n\n";
msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
if (confirm(msg)) { story.saveTiddler(tid); story.closeTiddler(tid); }
}
else
story.closeTiddler(this.crumbs[c]);
}
limit--;
}
}
}
};
if (config.macros.breadcrumbs.homeSeparator==undefined) // note: not a cookie
config.macros.breadcrumbs.homeSeparator=" | ";
if (config.macros.breadcrumbs.crumbSeparator==undefined) // note: not a cookie
config.macros.breadcrumbs.crumbSeparator=" > ";
config.commands.previousTiddler = {
text: 'back',
tooltip: 'view the previous tiddler',
hideReadOnly: false,
dateFormat: 'DDD, MMM DDth YYYY hh:0mm:0ss',
handler: function(event,src,title) {
var here=story.findContainingTiddler(src); if (!here) return;
var crumbs=config.macros.breadcrumbs.crumbs;
if (crumbs.length>1) {
var crumb=crumbs[crumbs.length-2];
story.displayTiddler(here,crumb);
}
else
config.macros.breadcrumbs.home();
return false;
}
};
config.macros.previousTiddler= {
label: 'back',
prompt: 'view the previous tiddler',
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var label=params.shift(); if (!label) label=this.label;
var prompt=params.shift(); if (!prompt) prompt=this.prompt;
createTiddlyButton(place,label,prompt,function() {
var crumbs=config.macros.breadcrumbs.crumbs;
if (crumbs.length>1) {
var crumb=crumbs[crumbs.length-2];
story.displayTiddler(place,crumb);
}
else
config.macros.breadcrumbs.home();
});
}
}
// hijack story.displayTiddler() so crumbs can be refreshed when a tiddler is displayed
if (Story.prototype.breadCrumbs_coreDisplayTiddler==undefined)
Story.prototype.breadCrumbs_coreDisplayTiddler=Story.prototype.displayTiddler;
Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
{
var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
this.breadCrumbs_coreDisplayTiddler.apply(this,arguments);
// if not displaying tiddler during document startup, then add it to the breadcrumbs
// note: 'startingUp' flag is a global, set/reset by the core init() function
if (!startingUp || config.options.chkShowStartupBreadcrumbs) config.macros.breadcrumbs.add(title);
}
// hijack store.removeTiddler() so crumbs can be refreshed when a tiddler is deleted
if (TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler==undefined)
TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler=TiddlyWiki.prototype.removeTiddler;
TiddlyWiki.prototype.removeTiddler= function(title)
{
this.breadCrumbs_coreRemoveTiddler.apply(this,arguments);
config.macros.breadcrumbs.refresh();
}
//}}}
/***
|Name|BreadcrumbsPluginInfo|
|Author|Eric Shulman|
|Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|
|Documentation|http://www.TiddlyTools.com/#BreadcrumbsPluginInfo|
|Version|2.0.0|
|License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.displayTiddler,TiddlyWiki.prototype.removeTiddler|
|Description|Documentation for BreadcrumbsPlugin|
This plugin provides a list of links to all tiddlers opened during the session, creating a "trail of breadcrumbs" from one tiddler to the next, allowing you to quickly navigate to any previously viewed tiddler, or select 'home' to reset the display to the initial set of tiddlers that were open at the start of the session (i.e., when the document was loaded into the browser).
!!!!!Usage
<<<
syntax:
{{{
<<breadcrumbs homeSeparator crumbSeparator>>
}}}
By default, the breadcrumbs are displayed as a continuous, //horizontal// word-wrapped line of text, using default character sequences for ''homeSeparator'' (" | ") and ''crumbSeparator'' (" > "). The //optional// ''homeSeparator'' and ''crumbSeparator'' macro parameters allow you to specify alternative separators. For example, to display the breadcrumbs //vertically// (in a stack, rather than a row), set the separator values to use {{{[[<br>]]}}}... and, to display a horizontal line as the home separator, use {{{[[<html><hr></html>]]}}}.
<<<
!!!!!Examples:
<<<
{{{
<<breadcrumbs>>
}}}
<<breadcrumbs>>
{{{
<<breadcrumbs [[<html><hr></html>]] [[<br>]]>>
}}}
<<breadcrumbs [[<html><hr></html>]] [[<br>]]>>
<<<
!!!!!Customization
<<<
Using CSS and a few of the plugin configuration options (see below), you can make the breadcrumbs display resemble browser tabs by adding the following to your [[StyleSheet]]:
{{{
.breadCrumbs { border-bottom:1px solid; }
.breadCrumbs a {
border: 1px solid; padding: 0px 1em;
-moz-border-radius-topleft:.5em; -moz-border-radius-topright:.5em;
-webkit-border-top-left-radius:.5em; -webkit-border-top-right-radius:.5em;
}
}}}
and this in [[ConfigTweaks]] (tagged with systemConfig, of course):
{{{
config.options.chkShowStartupBreadcrumbs=true;
config.options.chkBreadcrumbsLimitOpenTiddlers=true;
config.options.txtBreadcrumbsLimitOpenTiddlers=1;
config.macros.breadcrumbs.homeSeparator=" ";
config.macros.breadcrumbs.crumbSeparator=" ";
}}}
<<<
!!!!!Configuration
<<<
__''display placement:''__
<<option chkCreateDefaultBreadcrumbs>> automatically create breadcrumbs display (if needed)
{{{<<option chkCreateDefaultBreadcrumbs>>}}}
>By default, the plugin automatically creates the "breadCrumbs" display element at the top of the story column, just above the tiddlerDisplay area. To manually control the display and placement of the breadcrumbs display, you can define a DIV with class="breadCrumbs" in a custom [[PageTemplate]] or embed the {{{<<breadcrumbs>>}}} macro in specific tiddler content.
>
>For example, to add the breadcrumbs below the mainMenu, change this:
{{{
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
}}}
>to:
{{{
<div id='mainMenu'>
<div refresh='content' tiddler='MainMenu'></div>
<div id='breadCrumbs' class='breadCrumbs'></div>
</div>
}}}
>You can also block automatic creation of the breadcrumbs display by setting
{{{
config.options.chkCreateDefaultBreadcrumbs=false;
}}}
>in a [[CookieJar]]/[[ConfigTweaks]] plugin tiddler.
__''other settings:''__
<<option chkShowBreadcrumbs>> show/hide breadcrumbs display
{{{<<option chkShowBreadcrumbs>>}}}
>This checkbox toggles the visibility of the breadcrumbs display. However, the display is not updated until the next crumb is added (or a previous crumb is clicked on). For immediate effect, the [[ToggleBreadcrumbs]] script uses [[InlineJavascriptPlugin]] to synchronize the checkbox setting and the breadcrumbs display.
<<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler
{{{<<option chkReorderBreadcrumbs>>}}}
>When visiting a previously viewed tiddler, the title of the most-recently displayed tiddler is simply moved to the end of the list and individual breadcrumbs are not removed from the list unless the underlying tiddler is deleted. When ''re-ordering'' is disabled, the breadcrumbs list is ''trimmed'' so that all crumbs following that tiddler are removed from the list.
<<option chkBreadcrumbsHideHomeLink>> omit 'Home' link from breadcrumbs display
{{{<<option chkBreadcrumbsHideHomeLink>>}}}
>Enabling this option suppresses the automatic display of the "Home" link (and home separator). To manually add the home link elsewhere in your document, use the following HTML:
{{{
<html><a href="javascript:;" onclick="config.macros.breadcrumbs.home()">home</a></html>
}}}
<<option chkShowStartupBreadcrumbs>> show breadcrumbs for 'startup' tiddlers
{{{<<option chkShowStartupBreadcrumbs>>}}}
>Breadcrumbs are usually only added for tiddlers that are opened after the document has been loaded, and not for tiddlers displayed during initial startup (e.g., [[DefaultTiddlers]]). Enabling this option displays breadcrumbs for all viewed tiddlers, regardless of when they are opened.
<<option chkBreadcrumbsReverse>> show breadcrumbs in reverse order
{{{<<option chkBreadcrumbsReverse>>}}}
>As tiddlers are displayed, breadcrumbs are usually added to the //end// of the list. Enabling this option displays breadcrumbs in reverse order, so that the most recently visited tiddlers are listed first.
<<option chkBreadcrumbsLimit>> limit breadcrumbs display to {{twochar{<<option txtBreadcrumbsLimit>>}}} items
{{{<<option chkBreadcrumbsLimit>>}}} and {{{<<option txtBreadcrumbsLimit>>}}}
>By default, breadcrumbs are displayed for all tiddlers that have been visited (unless the list is being 'trimmed' by disabling the chkReorderBreadcrumbs option above). Enabling this option limits the display of the list to a maximum specified number of breadcrumbs.
<<option chkBreadcrumbsLimitOpenTiddlers>> limit open tiddlers to {{twochar{<<option txtBreadcrumbsLimitOpenTiddlers>>}}} items
{{{<<option chkBreadcrumbsLimitOpenTiddlers>>}}} and {{{<<option txtBreadcrumbsLimitOpenTiddlers>>}}}
>By default, tiddlers remain open (e.g., displayed in the story column) until you explicitly close them. When this option is enabled, only the most recently opened tiddlers will remain open: ''any tiddlers in excess of the specified limit are automatically closed.'' //Note: for 'data safety', if a tiddler is being edited, you will be asked for permission to "save-and-close" that tiddler or leave it open (even if that would exceed the specified limit).//
<<<
!!!!!Revisions
<<<
2008.05.01 [2.0.0] added 'limit open tiddlers' feature (with safety check for tiddler in edit mode)
2008.04.06 [1.9.1] corrected 'limit' logic so that //last// N crumbs are shown instead of //first// N crumbs. Also, added chkBreadcrumbsHideHomeLink
2008.04.04 [1.9.0] added chkBreadcrumbsReverse and chk/txtBreadcrumbsLimit
2008.03.29 [1.8.4] in displayTiddler(), get title from tiddler object (if needed). Fixes errors caused when calling function passes a tiddler *object* instead of a tiddler *title*
2008.03.24 [1.8.3] include shadow tiddlers in breadcrumbs list. Also changed settings so that "reordering" breadcrumbs is the default, instead of "trimming" the list
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.10.26 [1.8.2] documentation cleanup
2007.10.18 [1.8.1] in GetAreas(), use try/catch to avoid "Bad NPObject as private data" fatal error caused when embedded QuickTime player element is accessed by hasClass() function.
2007.10.02 [1.8.0] major documentation and code cleanup. Moved config.breadCrumbs.* to config.macros.breadcrumbs.* to consolidate objects. Also, fixed homeSeparator and crumbSeparator default handling.
2007.10.02 [1.7.0] added config.options.chkShowStartupBreadcrumbs option
2007.09.16 [1.6.1] in getAreas(), removed errant use of 'place' (was causing fatal error when creating default breadcrumbs display element). Also, added chkCreateDefaultBreadcrumbs configuration setting to enable/disable automatic creation of a default breadcrumbs display.
2007.09.16 [1.6.0] re-wrote refresh() to enable multiple display instances, by finding elements with "breadCrumbs" classname. Fallback to fixed ID (="breadCrumbs") is still used for backward-compatibility. move rendering code from refresh() to separate render() function, and added definition for {{{<<breadCrumbs>>}}} macro to support embedding breadcrumbs displays in tiddler content.
2007.09.15 [1.5.9.1] updated documentation
2007.09.15 [1.5.9] defined homeSeparator (" | ") and crumbSeparator (" > ") as object properties so that they can be redefined as desired for different layouts (e.g., using 'newline' for the crumbSeparator will arrange crumbs in a column rather than a row.
2007.06.21 [1.5.8.1] in home(), return false to prevent IE from attempting to navigate away...
2007.05.26 [1.5.8] added support for {{{<<option chkReorderBreadcrumbs>>}}} to toggle trim vs. re-order behavior when visiting previously viewed tiddlers
2007.05.25 [1.5.7] added support for {{{<<option chkShowBreadcrumbs>>}}} to toggle //display// of breadcrumbs
2007.05.24 [1.5.6] in refresh(), remove non-existing tiddler titles from crumb list. Also, hijack removeTiddler() so crumbs can be updated after tiddler is deleted.
2007.04.11 [1.5.5] added optional params to previousTiddler macro handler() to allow alternative label and tooltip text (instead of default "back")
2007.03.02 [1.5.4] in refresh(), for TW2.2, look for "storyDisplay" instead of "tiddlerDisplay" but keep fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.02.24 [1.5.3] changed from hijack of onClickTiddlerLink to hijack of displayTiddler() so that ALL displayed tiddlers are recorded in the crumbs, including programmatically displayed tiddlers opened by macros, scripts, etc., (such as [[GotoPlugin]], among many others) in addition to those opened by clicks on links.
2007.02.24 [1.5.2.0] eliminated global space clutter by moving function and data declarations so they are contained inside config.breadCrumbs object.
2007.02.06 [1.5.1] added "previousTiddler" macro (for use in sidebar)
2007.02.05 [1.5.0] added "previousTiddler" toolbar command (aka, "back")
2006.08.04 [1.4.0.1] change spaces to tabs
2006.08.04 [1.4.0] modified from 1.4.0 distro: in refresh(), set {{{display:none/block}}} instead of {{{visibility:hidden/visible}}}. In home(), check for valid crumbArea before setting style.
2006.08.02 [1.4.0] Fixed bug, the redefined onClickTiddlerLink_orig_breadCrumbs works incorrectly on IE
2006.07.20 [1.3.0] Runs compatibly with TW 2.1.0 (rev #403+)
2006.02.07 [1.2.0] change global array breadCrumbs to config.breadCrumbs by Eric's suggestion
2006.02.04 [1.1.0] JSLint checked
2006.02.01 [1.0.0] initial release
<<<
<html>
Here is a copy of my <a href="avestimehr-cv.pdf">CV</a>.
</html>
/***
|Name|CalendarPlugin|
|Source|http://www.TiddlyTools.com/#CalendarPlugin|
|Version|2008.09.09|
|Author|Eric Shulman|
|Original Author|SteveRumsby|
|License|unknown|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|display monthly and yearly calendars|
NOTE: For enhanced date display (including popups), you must also install [[DatePlugin]]
!!!!!Usage:
<<<
|{{{<<calendar>>}}}|Produce a full-year calendar for the current year|
|{{{<<calendar year>>}}}|Produce a full-year calendar for the given year|
|{{{<<calendar year month>>}}}|Produce a one-month calendar for the given month and year|
|{{{<<calendar thismonth>>}}}|Produce a one-month calendar for the current month|
|{{{<<calendar lastmonth>>}}}|Produce a one-month calendar for last month|
|{{{<<calendar nextmonth>>}}}|Produce a one-month calendar for next month|
|{{{<<calendar +n>>}}}<br>{{{<<calendar -n>>}}}|Produce a one-month calendar for a month +/- 'n' months from now|
<<<
!!!!!Configuration:
<<<
|''First day of week:''<br>{{{config.options.txtCalFirstDay}}}|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
|''First day of weekend:''<br>{{{config.options.txtCalStartOfWeekend}}}|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|
<<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
|''Week number display format:''<br>{{{config.options.txtWeekNumberDisplayFormat }}}|<<option txtWeekNumberDisplayFormat >>|
|''Week number link format:''<br>{{{config.options.txtWeekNumberLinkFormat }}}|<<option txtWeekNumberLinkFormat >>|
<<<
!!!!!Revisions
<<<
2008.09.10: added "+n" (and "-n") param to permit display of relative months (e.g., "+6" means "six months from now", "-3" means "three months ago". Based on suggestion from Jean.
2008.06.17: added support for config.macros.calendar.todaybg
2008.02.27: in handler(), DON'T set hard-coded default date format, so that *customized* value (pre-defined in config.macros.calendar.journalDateFmt is used.
2008.02.17: in createCalendarYear(), fix next/previous year calculation (use parseInt() to convert to numeric value). Also, use journalDateFmt for date linking when NOT using [[DatePlugin]].
2008.02.16: in createCalendarDay(), week numbers now created as TiddlyLinks, allowing quick creation/navigation to 'weekly' journals (based on request from Kashgarinn)
2008.01.08: in createCalendarMonthHeader(), "month year" heading is now created as TiddlyLink, allowing quick creation/navigation to 'month-at-a-time' journals
2007.11.30: added "return false" to onclick handlers (prevent IE from opening blank pages)
2006.08.23: added handling for weeknumbers (code supplied by Martin Budden (see "wn**" comment marks). Also, incorporated updated by Jeremy Sheeley to add caching for reminders (see [[ReminderMacros]], if installed)
2005.10.30: in config.macros.calendar.handler(), use "tbody" element for IE compatibility. Also, fix year calculation for IE's getYear() function (which returns '2005' instead of '105'). Also, in createCalendarDays(), use showDate() function (see [[DatePlugin]], if installed) to render autostyled date with linked popup. Updated calendar stylesheet definition: use .calendar class-specific selectors, add text centering and margin settings
2006.05.29: added journalDateFmt handling
<<<
***/
/***
!!!!!Code section:
***/
//{{{
version.extensions.CalendarPlugin= { major: 0, minor: 7, revision: 0, date: new Date(2008, 6, 17)};
if(config.options.txtCalFirstDay == undefined)
config.options.txtCalFirstDay = 0;
if(config.options.txtCalStartOfWeekend == undefined)
config.options.txtCalStartOfWeekend = 5;
if(config.options.chkDisplayWeekNumbers == undefined)//wn**
config.options.chkDisplayWeekNumbers = false;
if(config.options.chkDisplayWeekNumbers)
config.options.txtCalFirstDay = 0;
if(config.options.txtWeekNumberDisplayFormat == undefined)//wn**
config.options.txtWeekNumberDisplayFormat = "w0WW";
if(config.options.txtWeekNumberLinkFormat == undefined)//wn**
config.options.txtWeekNumberLinkFormat = "YYYY-w0WW";
config.macros.calendar = {};
config.macros.calendar.monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.macros.calendar.daynames = ["M", "T", "W", "T", "F", "S", "S"];
config.macros.calendar.todaybg = "#ccccff";
config.macros.calendar.weekendbg = "#c0c0c0";
config.macros.calendar.monthbg = "#e0e0e0";
config.macros.calendar.holidaybg = "#ffc0c0";
config.macros.calendar.journalDateFmt = "DD MMM YYYY";
config.macros.calendar.monthdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
config.macros.calendar.holidays = [ ]; // Not sure this is required anymore - use reminders instead
//}}}
//{{{
function calendarIsHoliday(date) // Is the given date a holiday?
{
var longHoliday = date.formatString("0DD/0MM/YYYY");
var shortHoliday = date.formatString("0DD/0MM");
for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
if(config.macros.calendar.holidays[i] == longHoliday || config.macros.calendar.holidays[i] == shortHoliday)
return true;
}
return false;
}
//}}}
//{{{
config.macros.calendar.handler = function(place,macroName,params) {
var calendar = createTiddlyElement(place, "table", null, "calendar", null);
var tbody = createTiddlyElement(calendar, "tbody", null, null, null);
var today = new Date();
var year = today.getYear();
if (year<1900) year+=1900;
// get format for journal link by reading from SideBarOptions (ELS 5/29/06 - based on suggestion by Martin Budden)
var text = store.getTiddlerText("SideBarOptions");
var re = new RegExp("<<(?:newJournal)([^>]*)>>","mg"); var fm = re.exec(text);
if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }
var month=-1;
if (params[0] == "thismonth") {
var month=today.getMonth();
} else if (params[0] == "lastmonth") {
var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
} else if (params[0] == "nextmonth") {
var month = today.getMonth()+1; if (month>11) { month=0; year++; }
} else if (params[0]&&"+-".indexOf(params[0].substr(0,1))!=-1) {
var month = today.getMonth()+parseInt(params[0]);
if (month>11) { year+=Math.floor(month/12); month%=12; };
if (month<0) { year+=Math.floor(month/12); month=12+month%12; }
} else if (params[0]) {
year = params[0];
if(params[1]) month=parseInt(params[1])-1;
if (month>11) month=11; if (month<0) month=0;
}
if (month!=-1) {
cacheReminders(new Date(year, month, 1, 0, 0), 31);
createCalendarOneMonth(tbody, year, month);
} else {
cacheReminders(new Date(year, 0, 1, 0, 0), 366);
createCalendarYear(tbody, year);
}
window.reminderCacheForCalendar = null;
}
//}}}
//{{{
//This global variable is used to store reminders that have been cached
//while the calendar is being rendered. It will be renulled after the calendar is fully rendered.
window.reminderCacheForCalendar = null;
//}}}
//{{{
function cacheReminders(date, leadtime)
{
if (window.findTiddlersWithReminders == null) return;
window.reminderCacheForCalendar = {};
var leadtimeHash = [];
leadtimeHash [0] = 0;
leadtimeHash [1] = leadtime;
var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
for(var i = 0; i < t.length; i++) {
//just tag it in the cache, so that when we're drawing days, we can bold this one.
window.reminderCacheForCalendar[t[i]["matchedDate"]] = "reminder:" + t[i]["params"]["title"];
}
}
//}}}
//{{{
function createCalendarOneMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, true, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarMonth(calendar, year, mon)
{
var row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon] + " " + year, false, year, mon);
row = createTiddlyElement(calendar, "tr", null, null, null);
createCalendarDayHeader(row, 1);
createCalendarDayRowsSingle(calendar, year, mon);
}
//}}}
//{{{
function createCalendarYear(calendar, year)
{
var row;
row = createTiddlyElement(calendar, "tr", null, null, null);
var back = createTiddlyElement(row, "td", null, null, null);
var backHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, parseInt(year)-1);
return false; // consume click
};
createTiddlyButton(back, "<", "Previous year", backHandler);
back.align = "center";
var yearHeader = createTiddlyElement(row, "td", null, "calendarYear", year);
yearHeader.align = "center";
yearHeader.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?22:19);//wn**
var fwd = createTiddlyElement(row, "td", null, null, null);
var fwdHandler = function() {
removeChildren(calendar);
createCalendarYear(calendar, parseInt(year)+1);
return false; // consume click
};
createTiddlyButton(fwd, ">", "Next year", fwdHandler);
fwd.align = "center";
createCalendarMonthRow(calendar, year, 0);
createCalendarMonthRow(calendar, year, 3);
createCalendarMonthRow(calendar, year, 6);
createCalendarMonthRow(calendar, year, 9);
}
//}}}
//{{{
function createCalendarMonthRow(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDayHeader(row, 3);
createCalendarDayRows(cal, year, mon);
}
//}}}
//{{{
function createCalendarMonthHeader(cal, row, name, nav, year, mon)
{
var month;
if (nav) {
var back = createTiddlyElement(row, "td", null, null, null);
back.align = "center";
back.style.background = config.macros.calendar.monthbg;
var backMonHandler = function() {
var newyear = year;
var newmon = mon-1;
if(newmon == -1) { newmon = 11; newyear = newyear-1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
};
createTiddlyButton(back, "<", "Previous month", backMonHandler);
month = createTiddlyElement(row, "td", null, "calendarMonthname")
createTiddlyLink(month,name,true);
month.setAttribute("colSpan", config.options.chkDisplayWeekNumbers?6:5);//wn**
var fwd = createTiddlyElement(row, "td", null, null, null);
fwd.align = "center";
fwd.style.background = config.macros.calendar.monthbg;
var fwdMonHandler = function() {
var newyear = year;
var newmon = mon+1;
if(newmon == 12) { newmon = 0; newyear = newyear+1;}
removeChildren(cal);
cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
createCalendarOneMonth(cal, newyear, newmon);
return false; // consume click
};
createTiddlyButton(fwd, ">", "Next month", fwdMonHandler);
} else {
month = createTiddlyElement(row, "td", null, "calendarMonthname", name)
month.setAttribute("colSpan",config.options.chkDisplayWeekNumbers?8:7);//wn**
}
month.align = "center";
month.style.background = config.macros.calendar.monthbg;
}
//}}}
//{{{
function createCalendarDayHeader(row, num)
{
var cell;
for(var i = 0; i < num; i++) {
if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, "td");//wn**
for(var j = 0; j < 7; j++) {
var d = j + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
cell = createTiddlyElement(row, "td", null, null, config.macros.calendar.daynames[d]);
if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
cell.style.background = config.macros.calendar.weekendbg;
}
}
}
//}}}
//{{{
function createCalendarDays(row, col, first, max, year, mon) {
var i;
if (config.options.chkDisplayWeekNumbers){
if (first<=max) {
var ww = new Date(year,mon,first);
var td=createTiddlyElement(row, "td");//wn**
var link=createTiddlyLink(td,ww.formatString(config.options.txtWeekNumberLinkFormat),false);
link.appendChild(document.createTextNode(ww.formatString(config.options.txtWeekNumberDisplayFormat)));
}
else createTiddlyElement(row, "td", null, null, null);//wn**
}
for(i = 0; i < col; i++)
createTiddlyElement(row, "td", null, null, null);
var day = first;
for(i = col; i < 7; i++) {
var d = i + (config.options.txtCalFirstDay - 0);
if(d > 6) d = d - 7;
var daycell = createTiddlyElement(row, "td", null, null, null);
var isaWeekend = ((d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))? true:false);
if(day > 0 && day <= max) {
var celldate = new Date(year, mon, day);
// ELS 2005.10.30: use <<date>> macro's showDate() function to create popup
// ELS 5/29/06 - use journalDateFmt
if (window.showDate)
showDate(daycell,celldate,"popup","DD",config.macros.calendar.journalDateFmt,true, isaWeekend);
else {
if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
var title = celldate.formatString(config.macros.calendar.journalDateFmt);
if(calendarIsHoliday(celldate))
daycell.style.background = config.macros.calendar.holidaybg;
var now=new Date();
if ((now-celldate>=0) && (now-celldate<86400000)) // is today?
daycell.style.background = config.macros.calendar.todaybg;
if(window.findTiddlersWithReminders == null) {
var link = createTiddlyLink(daycell, title, false);
link.appendChild(document.createTextNode(day));
} else
var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
}
}
day++;
}
}
//}}}
//{{{
// We've clicked on a day in a calendar - create a suitable pop-up of options.
// The pop-up should contain:
// * a link to create a new entry for that date
// * a link to create a new reminder for that date
// * an <hr>
// * the list of reminders for that date
// NOTE: The following code is only used when [[DatePlugin]] is not present
function onClickCalendarDate(e)
{
var button = this;
var date = button.getAttribute("title");
var dat = new Date(date.substr(6,4), date.substr(3,2)-1, date.substr(0, 2));
date = dat.formatString(config.macros.calendar.journalDateFmt);
var popup = createTiddlerPopup(this);
popup.appendChild(document.createTextNode(date));
var newReminder = function() {
var t = store.getTiddlers(date);
displayTiddler(null, date, 2, null, null, false, false);
if(t) {
document.getElementById("editorBody" + date).value += "\n<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) + " year:" + (dat.getYear()+1900) + " title: >>";
} else {
document.getElementById("editorBody" + date).value = "<<reminder day:" + dat.getDate() +
" month:" + (dat.getMonth()+1) +" year:" + (dat.getYear()+1900) + " title: >>";
}
return false; // consume click
};
var link = createTiddlyButton(popup, "New reminder", null, newReminder);
popup.appendChild(document.createElement("hr"));
var t = findTiddlersWithReminders(dat, [0,14], null, 1);
for(var i = 0; i < t.length; i++) {
link = createTiddlyLink(popup, t[i].tiddler, false);
link.appendChild(document.createTextNode(t[i].tiddler));
}
return false; // consume click
}
//}}}
//{{{
function calendarMaxDays(year, mon)
{
var max = config.macros.calendar.monthdays[mon];
if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) max++;
return max;
}
//}}}
//{{{
function createCalendarDayRows(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1 + 7;
var day1 = -first1 + 1;
var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first2 < 0) first2 = first2 + 7;
var day2 = -first2 + 1;
var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first3 < 0) first3 = first3 + 7;
var day3 = -first3 + 1;
var max1 = calendarMaxDays(year, mon);
var max2 = calendarMaxDays(year, mon+1);
var max3 = calendarMaxDays(year, mon+2);
while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
}
}
//}}}
//{{{
function createCalendarDayRowsSingle(cal, year, mon)
{
var row = createTiddlyElement(cal, "tr", null, null, null);
var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
if(first1 < 0) first1 = first1+ 7;
var day1 = -first1 + 1;
var max1 = calendarMaxDays(year, mon);
while(day1 <= max1) {
row = createTiddlyElement(cal, "tr", null, null, null);
createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
}
}
//}}}
//{{{
setStylesheet(".calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }", "calendarStyles");
//}}}
// // override cookie settings for CalendarPlugin:
//{{{
config.options.txtCalFirstDay=6;
config.options.txtCalStartOfWeekend=5;
//}}}
// // override internal default settings for CalendarPlugin:
//{{{
config.macros.calendar.journalDateFmt="DDD MMM 0DD YYYY";
//}}}
<div macro='gradient vert #06a #058'><div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler templateChooser collapseOthers expandTiddler permalink references jump'></div>
<div class='title' macro='view title'></div></div>
<html>
<font size="3" color=#BF2323> Salman Avestimehr </font>
<br>
<b>E-mail:</b> <font color=darkblue>avestimehr at ece dot cornell dot edu </font> also <font color=darkblue>avestime at caltech dot edu </font>
<br>
<b>Mailing address: </b>
<br> 327 Moore, MC 136-93
<br> California Institute of Technology
<br> 1200 E. California Blvd
<br> Pasadena, CA 91125
</html>
/***
|Name|DatePlugin|
|Source|http://www.TiddlyTools.com/#DatePlugin|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|formatted dates plus popup menu with 'journal' link, changes and (optional) reminders|
There are quite a few calendar generators, reminders, to-do lists, 'dated tiddlers' journals, blog-makers and GTD-like schedule managers that have been built around TW. While they all have different purposes, and vary in format, interaction, and style, in one way or another each of these plugins displays and/or uses date-based information to make finding, accessing and managing relevant tiddlers easier. This plugin provides a general approach to embedding dates and date-based links/menus within tiddler content.
!!!!!Documentation
>see [[DatePluginInfo]]
!!!!!Configuration
<<<
<<option chkDatePopupHideCreated>> omit 'created' section from date popups
<<option chkDatePopupHideChanged>> omit 'changed' section from date popups
<<option chkDatePopupHideTagged>> omit 'tagged' section from date popups
<<option chkDatePopupHideReminders>> omit 'reminders' section from date popups
<<option chkShowJulianDate>> display Julian day number (1-365) below current date
see [[DatePluginConfig]] for additional configuration settings, for use in calendar displays, including:
*date formats
*color-coded backgrounds
*annual fixed-date holidays
*weekends
<<<
!!!!!Revisions
<<<
2008.03.08 [2.7.0] in addModifiedsToPopup(), if a tiddler was created on the specified date, don't list it in the 'changed' section of the popup. Based on a request from Kashgarinn.
|please see [[DatePluginInfo]] for additional revision details|
2005.10.30 [0.9.0] pre-release
<<<
!!!!!Code
***/
//{{{
version.extensions.DatePlugin= {major: 2, minor: 7, revision: 0, date: new Date(2008,3,8)};
config.macros.date = {
format: "YYYY.0MM.0DD", // default date display format
linkformat: "YYYY.0MM.0DD", // 'dated tiddler' link format
linkedbg: "#babb1e", // "babble"
todaybg: "#ffab1e", // "fable"
weekendbg: "#c0c0c0", // "cocoa"
holidaybg: "#ffaace", // "face"
createdbg: "#bbeeff", // "beef"
modifiedsbg: "#bbeeff", // "beef"
remindersbg: "#c0ffee", // "coffee"
holidays: [ "01/01", "07/04", "07/24", "11/24" ], // NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)
weekend: [ 1,0,0,0,0,0,1 ] // [ day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 ]
};
config.macros.date.handler = function(place,macroName,params)
{
// do we want to see a link, a popup, or just a formatted date?
var mode="display";
if (params[0]=="display") { mode=params[0]; params.shift(); }
if (params[0]=="popup") { mode=params[0]; params.shift(); }
if (params[0]=="link") { mode=params[0]; params.shift(); }
// get the date
var now = new Date();
var date = now;
if (!params[0] || params[0]=="today")
{ params.shift(); }
else if (params[0]=="filedate")
{ date=new Date(document.lastModified); params.shift(); }
else if (params[0]=="tiddler")
{ date=store.getTiddler(story.findContainingTiddler(place).id.substr(7)).modified; params.shift(); }
else if (params[0].substr(0,8)=="tiddler:")
{ var t; if ((t=store.getTiddler(params[0].substr(8)))) date=t.modified; params.shift(); }
else {
var y = eval(params.shift().replace(/Y/ig,(now.getYear()<1900)?now.getYear()+1900:now.getYear()));
var m = eval(params.shift().replace(/M/ig,now.getMonth()+1));
var d = eval(params.shift().replace(/D/ig,now.getDate()+0));
date = new Date(y,m-1,d);
}
// date format with optional custom override
var format=this.format; if (params[0]) format=params.shift();
var linkformat=this.linkformat; if (params[0]) linkformat=params.shift();
showDate(place,date,mode,format,linkformat);
}
window.showDate=showDate;
function showDate(place,date,mode,format,linkformat,autostyle,weekend)
{
if (!mode) mode="display";
if (!format) format=config.macros.date.format;
if (!linkformat) linkformat=config.macros.date.linkformat;
if (!autostyle) autostyle=false;
// format the date output
var title = date.formatString(format);
var linkto = date.formatString(linkformat);
// just show the formatted output
if (mode=="display") { place.appendChild(document.createTextNode(title)); return; }
// link to a 'dated tiddler'
var link = createTiddlyLink(place, linkto, false);
link.appendChild(document.createTextNode(title));
link.title = linkto;
link.date = date;
link.format = format;
link.linkformat = linkformat;
// if using a popup menu, replace click handler for dated tiddler link
// with handler for popup and make link text non-italic (i.e., an 'existing link' look)
if (mode=="popup") {
link.onclick = onClickDatePopup;
link.style.fontStyle="normal";
}
// format the popup link to show what kind of info it contains (for use with calendar generators)
if (autostyle) setDateStyle(place,link,weekend);
}
//}}}
//{{{
// NOTE: This function provides default logic for setting the date style when displayed in a calendar
// To customize the date style logic, please see[[DatePluginConfig]]
function setDateStyle(place,link,weekend) {
// alias variable names for code readability
var date=link.date;
var fmt=link.linkformat;
var linkto=date.formatString(fmt);
var cmd=config.macros.date;
if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
{ place.style.background = cmd.weekendbg; }
if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
if (hasReminders(date))
{ link.style.textDecoration="underline"; }
if (isToday(date))
{ link.style.border="1px solid black"; }
if (isHoliday(date)&&(cmd.holidaybg!=""))
{ place.style.background = cmd.holidaybg; }
if (hasCreateds(date)&&(cmd.createdbg!=""))
{ place.style.background = cmd.createdbg; }
if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
{ place.style.background = cmd.modifiedsbg; }
if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
{ place.style.background = cmd.linkedbg; }
if (hasReminders(date)&&(cmd.remindersbg!=""))
{ place.style.background = cmd.remindersbg; }
if (isToday(date)&&(cmd.todaybg!=""))
{ place.style.background = cmd.todaybg; }
if (config.options.chkShowJulianDate) { // optional display of Julian date numbers
var m=[0,31,59,90,120,151,181,212,243,273,304,334];
var d=date.getDate()+m[date.getMonth()];
var y=date.getFullYear();
if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0)
d++; // after February in a leap year
wikify("@@font-size:80%;<br>"+d+"@@",place);
}
}
//}}}
//{{{
function isToday(date) // returns true if date is today
{ var now=new Date(); return ((now-date>=0) && (now-date<86400000)); }
function isWeekend(date) // returns true if date is a weekend
{ return (config.macros.date.weekend[date.getDay()]); }
function isHoliday(date) // returns true if date is a holiday
{
var longHoliday = date.formatString("0MM/0DD/YYYY");
var shortHoliday = date.formatString("0MM/0DD");
for(var i = 0; i < config.macros.date.holidays.length; i++) {
var holiday=config.macros.date.holidays[i];
if (holiday==longHoliday||holiday==shortHoliday) return true;
}
return false;
}
//}}}
//{{{
// Event handler for clicking on a day popup
function onClickDatePopup(e)
{
if (!e) var e = window.event;
var theTarget = resolveTarget(e);
var popup = Popup.create(this);
if(popup) {
// always show dated tiddler link (or just date, if readOnly) at the top...
if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))
createTiddlyLink(popup,this.date.formatString(this.linkformat),true);
else
createTiddlyText(popup,this.date.formatString(this.linkformat));
if (!config.options.chkDatePopupHideCreated)
addCreatedsToPopup(popup,this.date,this.format);
if (!config.options.chkDatePopupHideChanged)
addModifiedsToPopup(popup,this.date,this.format);
if (!config.options.chkDatePopupHideTagged)
addTaggedToPopup(popup,this.date,this.linkformat);
if (!config.options.chkDatePopupHideReminders)
addRemindersToPopup(popup,this.date,this.linkformat);
}
Popup.show(popup,false);
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
return(false);
}
//}}}
//{{{
function indexCreateds() // build list of tiddlers, hash indexed by creation date
{
var createds= { };
var tiddlers = store.getTiddlers("title","excludeLists");
for (var t = 0; t < tiddlers.length; t++) {
var date = tiddlers[t].created.formatString("YYYY0MM0DD")
if (!createds[date])
createds[date]=new Array();
createds[date].push(tiddlers[t].title);
}
return createds;
}
function hasCreateds(date) // returns true if date has created tiddlers
{
if (!config.macros.date.createds) config.macros.date.createds=indexCreateds();
return (config.macros.date.createds[date.formatString("YYYY0MM0DD")]!=undefined);
}
function addCreatedsToPopup(popup,when,format)
{
var force=(store.isDirty() && when.formatString("YYYY0MM0DD")==new Date().formatString("YYYY0MM0DD"));
if (force || !config.macros.date.createds) config.macros.date.createds=indexCreateds();
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var createds = config.macros.date.createds[when.formatString("YYYY0MM0DD")];
if (createds) {
createds.sort();
var e=createTiddlyElement(popup,"div",null,null,"created ("+createds.length+")");
for(var t=0; t<createds.length; t++) {
var link=createTiddlyLink(popup,createds[t],false);
link.appendChild(document.createTextNode(indent+createds[t]));
createTiddlyElement(popup,"br",null,null,null);
}
}
}
//}}}
//{{{
function indexModifieds() // build list of tiddlers, hash indexed by modification date
{
var modifieds= { };
var tiddlers = store.getTiddlers("title","excludeLists");
for (var t = 0; t < tiddlers.length; t++) {
var date = tiddlers[t].modified.formatString("YYYY0MM0DD")
if (!modifieds[date])
modifieds[date]=new Array();
modifieds[date].push(tiddlers[t].title);
}
return modifieds;
}
function hasModifieds(date) // returns true if date has modified tiddlers
{
if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();
return (config.macros.date.modifieds[date.formatString("YYYY0MM0DD")]!=undefined);
}
function addModifiedsToPopup(popup,when,format)
{
var date=when.formatString("YYYY0MM0DD");
var force=(store.isDirty() && date==new Date().formatString("YYYY0MM0DD"));
if (force || !config.macros.date.modifieds) config.macros.date.modifieds=indexModifieds();
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var mods = config.macros.date.modifieds[date];
if (mods) {
// if a tiddler was created on this date, don't list it in the 'changed' section
if (config.macros.date.createds && config.macros.date.createds[date]) {
var temp=[];
for(var t=0; t<mods.length; t++)
if (!config.macros.date.createds[date].contains(mods[t]))
temp.push(mods[t]);
mods=temp;
}
mods.sort();
var e=createTiddlyElement(popup,"div",null,null,"changed ("+mods.length+")");
for(var t=0; t<mods.length; t++) {
var link=createTiddlyLink(popup,mods[t],false);
link.appendChild(document.createTextNode(indent+mods[t]));
createTiddlyElement(popup,"br",null,null,null);
}
}
}
//}}}
//{{{
function hasTagged(date,format) // returns true if date is tagging other tiddlers
{
return store.getTaggedTiddlers(date.formatString(format)).length>0;
}
function addTaggedToPopup(popup,when,format)
{
var indent=String.fromCharCode(160)+String.fromCharCode(160);
var tagged=store.getTaggedTiddlers(when.formatString(format));
if (tagged.length) var e=createTiddlyElement(popup,"div",null,null,"tagged ("+tagged.length+")");
for(var t=0; t<tagged.length; t++) {
var link=createTiddlyLink(popup,tagged[t].title,false);
link.appendChild(document.createTextNode(indent+tagged[t].title));
createTiddlyElement(popup,"br",null,null,null);
}
}
//}}}
//{{{
function indexReminders(date,leadtime) // build list of tiddlers with reminders, hash indexed by reminder date
{
var reminders = { };
if(window.findTiddlersWithReminders!=undefined) { // reminder plugin is installed
// DEBUG var starttime=new Date();
var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);
for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;
// DEBUG var out="Found "+t.length+" reminders in "+((new Date())-starttime+1)+"ms\n";
// DEBUG out+="startdate: "+date.toLocaleDateString()+"\n"+"leadtime: "+leadtime+" days\n\n";
// DEBUG for(var i=0; i<t.length; i++) { out+=t[i].matchedDate.toLocaleDateString()+" "+t[i].params.title+"\n"; }
// DEBUG alert(out);
}
return reminders;
}
function hasReminders(date) // returns true if date has reminders
{
if (window.reminderCacheForCalendar)
return window.reminderCacheForCalendar[date]; // use calendar cache
if (!config.macros.date.reminders)
config.macros.date.reminders = indexReminders(date,90); // create a 90-day leadtime reminder cache
return (config.macros.date.reminders[date]);
}
function addRemindersToPopup(popup,when,format)
{
if(window.findTiddlersWithReminders==undefined) return; // reminder plugin not installed
var indent = String.fromCharCode(160)+String.fromCharCode(160);
var reminders=findTiddlersWithReminders(when, [0,31],null,null,1);
createTiddlyElement(popup,"div",null,null,"reminders ("+(reminders.length||"none")+")");
for(var t=0; t<reminders.length; t++) {
link = createTiddlyLink(popup,reminders[t].tiddler,false);
var diff=reminders[t].diff;
diff=(diff<1)?"Today":((diff==1)?"Tomorrow":diff+" days");
var txt=(reminders[t].params["title"])?reminders[t].params["title"]:reminders[t].tiddler;
link.appendChild(document.createTextNode(indent+diff+" - "+txt));
createTiddlyElement(popup,"br",null,null,null);
}
if (readOnly) return; // omit "new reminder..." link
var link = createTiddlyLink(popup,indent+"new reminder...",true); createTiddlyElement(popup,"br");
var title = when.formatString(format);
link.title="add a reminder to '"+title+"'";
link.onclick = function() {
// show tiddler editor
story.displayTiddler(null, title, 2, null, null, false, false);
// find body 'textarea'
var c =document.getElementById("tiddler" + title).getElementsByTagName("*");
for (var i=0; i<c.length; i++) if ((c[i].tagName.toLowerCase()=="textarea") && (c[i].getAttribute("edit")=="text")) break;
// append reminder macro to tiddler content
if (i<c.length) {
if (store.tiddlerExists(title)) c[i].value+="\n"; else c[i].value="";
c[i].value += "<<reminder";
c[i].value += " day:"+when.getDate();
c[i].value += " month:"+(when.getMonth()+1);
c[i].value += " year:"+when.getFullYear();
c[i].value += ' title:"Enter a title" >>';
}
};
}
//}}}
/***
|Name|DatePluginConfig|
|Source|http://www.TiddlyTools.com/#DatePluginConfig|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.6.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|formats, background colors and other optional settings for DatePlugin|
***/
// // Default popup content display options (can be overridden by cookies)
//{{{
if (config.options.chkDatePopupHideCreated===undefined)
config.options.chkDatePopupHideCreated=false;
if (config.options.chkDatePopupHideChanged===undefined)
config.options.chkDatePopupHideChanged=false;
if (config.options.chkDatePopupHideTagged===undefined)
config.options.chkDatePopupHideTagged=false;
if (config.options.chkDatePopupHideReminders===undefined)
config.options.chkDatePopupHideReminders=false;
//}}}
// // show Julian date number below regular date
//{{{
if (config.options.chkShowJulianDate===undefined)
config.options.chkShowJulianDate=false;
//}}}
// // fixed-date annual holidays
//{{{
config.macros.date.holidays=[
"01/01", // NewYearsDay,
"07/04", // US Independence Day
"07/24" // Eric's Birthday (hooray!)
];
//}}}
// // weekend map (1=weekend, 0=weekday)
//{{{
config.macros.date.weekend=[ 1,0,0,0,0,0,1 ]; // day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6
//}}}
// // date display/link formats
//{{{
config.macros.date.format="YYYY.0MM.0DD"; // default date display format
config.macros.date.linkformat="YYYY.0MM.0DD"; // 'dated tiddler' link format
//}}}
// // When displaying a calendar (see [[CalendarPlugin]]), you can customize the colors/styles that are applied to the calendar dates by modifying the values and/or functions below:
//{{{
// default calendar colors
config.macros.date.weekendbg="#c0c0c0";
config.macros.date.holidaybg="#ffaace";
config.macros.date.createdbg="#bbeeff";
config.macros.date.modifiedsbg="#bbeeff";
config.macros.date.linkedbg="#babb1e";
config.macros.date.remindersbg="#c0ffee";
// apply calendar styles
function setDateStyle(place,link,weekend) {
// alias variable names for code readability
var date=link.date;
var fmt=link.linkformat;
var linkto=date.formatString(fmt);
var cmd=config.macros.date;
if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
{ place.style.background = cmd.weekendbg; }
if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
if (hasReminders(date))
{ link.style.textDecoration="underline"; }
if (isToday(date))
{ link.style.border="1px solid black"; }
if (isHoliday(date)&&(cmd.holidaybg!=""))
{ place.style.background = cmd.holidaybg; }
if (hasCreateds(date)&&(cmd.createdbg!=""))
{ place.style.background = cmd.createdbg; }
if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
{ place.style.background = cmd.modifiedsbg; }
if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
{ place.style.background = cmd.linkedbg; }
if (hasReminders(date)&&(cmd.remindersbg!=""))
{ place.style.background = cmd.remindersbg; }
if (isToday(date)&&(cmd.todaybg!=""))
{ place.style.background = cmd.todaybg; }
if (config.options.chkShowJulianDate) {
var m=[0,31,59,90,120,151,181,212,243,273,304,334];
var d=date.getDate()+m[date.getMonth()];
var y=date.getFullYear();
if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0) d++; // after February in a leap year
wikify("@@font-size:80%;<br>"+d+"@@",place);
}
}
//}}}
|Name|DatePluginInfo|
|Source|http://www.TiddlyTools.com/#DatePlugin|
|Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for DatePlugin|
There are quite a few calendar generators, reminders, to-do lists, 'dated tiddlers' journals, blog-makers and GTD-like schedule managers that have been built around TW. While they all have different purposes, and vary in format, interaction, and style, in one way or another each of these plugins displays and/or uses date-based information to make finding, accessing and managing relevant tiddlers easier. This plugin provides a general approach to embedding dates and date-based links/menus within tiddler content.
!!!!!Usage
<<<
This plugin display formatted dates, for the specified year, month, day using number values or mathematical expressions such as (Y+1) or (D+30). Optionally, you can create a link from the formatted output to a 'dated tiddler' for quick blogging or create a popup menu that includes the dated tiddler link plus links to tiddlers that were created/changed on that date, or are tagged with that date, as well as links to any pending reminders for the coming 31 days (if the RemindersPlugin is installed). This plugin also provides a public API for easily incorporating formatted date output (with or without the links/popups) into other plugins, such as calendar generators, etc.
This plugin defines a macro: {{{<<date [mode] [date] [format] [linkformat]>>}}}. All of the macro parameters are optional and, in it's simplest form, {{{<<date>>}}}, it is equivalent to the ~TiddlyWiki core macro, {{{<<today>>}}}.
However, where {{{<<today>>}}} simply inserts the current date/time in a predefined format (or custom format, using {{{<<today [format]>>}}}), the {{{<<date>>}}} macro's parameters take it much further than that:
* [mode] is either ''display'', ''link'' or ''popup''. If omitted, it defaults to ''display''. This param let's you select between simply displaying a formatted date, or creating a link to a specific 'date titled' tiddler or a popup menu containing a dated tiddler link, plus links to changes and reminders.
* [date] lets you enter ANY date (not just today) as ''year, month, and day values or simple mathematical expressions'' using pre-defined variables, Y, M, and D for the current year, month and day, repectively. You can display the modification date of the current tiddler by using the keyword: ''tiddler'' in place of the year, month and day parameters. Use ''tiddler://name-of-tiddler//'' to display the modification date of a specific tiddler. You can also use keywords ''today'' or ''filedate'' to refer to these //dynamically changing// date/time values.
* [format] and [linkformat] uses standard ~TiddlyWiki date formatting syntax. The default is "YYYY.0MM.0DD"
>^^''DDD'' - day of week in full (eg, "Monday"), ''DD'' - day of month, ''0DD'' - adds leading zero^^
>^^''MMM'' - month in full (eg, "July"), ''MM'' - month number, ''0MM'' - adds leading zero^^
>^^''YYYY'' - full year, ''YY'' - two digit year, ''hh'' - hours, ''mm'' - minutes, ''ss'' - seconds^^
>^^//note: use of hh, mm or ss format codes is only supported with ''tiddler'', ''today'' or ''filedate'' values//^^
* [linkformat] - specify an alternative date format so that the title of a 'dated tiddler' link can have a format that differs from the date's displayed format
In addition to the macro syntax, DatePlugin also provides a public javascript API so that other plugins that work with dates (such as calendar generators, etc.) can quickly incorporate date formatted links or popups into their output:
''{{{showDate(place, date, mode, format, linkformat, autostyle, weekend)}}}''
Note that in addition to the parameters provided by the macro interface, the javascript API also supports two optional true/false parameters:
* [autostyle] - when true, the font/background styles of formatted dates are automatically adjusted to show the date's status: 'today' is boxed, 'changes' are bold, 'reminders' are underlined, while weekends and holidays (as well as changes and reminders) can each have a different background color to make them more visibly distinct from each other.
* [weekend] - true indicates a weekend, false indicates a weekday. When this parameter is omitted, the plugin uses internal defaults to automatically determine when a given date falls on a weekend.
<<<
!!!!!Examples
<<<
The current date: <<date>>
The current time: <<date today "0hh:0mm:0ss">>
Today's blog: <<date link today "DDD, MMM DDth, YYYY">>
Recent blogs/changes/reminders: <<date popup Y M D-1 "yesterday">> <<date popup today "today">> <<date popup Y M D+1 "tomorrow">>
The first day of next month will be a <<date Y M+1 1 "DDD">>
This tiddler (DatePlugin) was last updated on: <<date tiddler "DDD, MMM DDth, YYYY">>
The SiteUrl was last updated on: <<date tiddler:SiteUrl "DDD, MMM DDth, YYYY">>
This document was last saved on <<date filedate "DDD, MMM DDth, YYYY at 0hh:0mm:0ss">>
<<date 2006 07 24 "MMM DDth, YYYY">> will be a <<date 2006 07 24 "DDD">>
<<<
!!!!!Revisions
<<<
2008.03.08 [2.7.0] in addModifiedsToPopup(), if a tiddler was created on the specified date, don't list it in the 'changed' section of the popup. Based on a request from Kashgarinn
2008.01.31 [2.6.0] refactored date style logic into separate setDateStyle() function so it can be overridden by a custom definition. See [[DatePluginConfig]].
2008.01.11 [2.5.0] added options to selectively suppress created/changes/tagged/reminders popup content
2008.01.08 [*.*.*] plugin size reduction: documentation moved to DatePluginInfo
2007.11.21 [2.4.0] added hasTagged() and addTaggedToPopup() to list any tiddlers that has been tagged using the title of the dated journal tiddler asa tag value (i.e., the tiddlers that will be listed in the standard "tagging" display when viewing the journal tiddler itself). Based on a request from Coby.
2007.06.20 [2.3.1] in onClickDatePopup(), use Popup.show() instead of deprecated ScrollToTiddlerPopup(). Fixes fatal error that prevents popups from being properly displayed
2007.05.31 [2.3.0] list "created" tiddlers in date popup. Also, force re-cache of created/modified indices when displaying current date and store.isDirty(), so that popup is kept in sync with tiddler changes.
2006.05.09 [2.2.1] added "todaybg" handling to set background color of current date. Also, honor excludeLists tag when getting lists of tiddlers. Based on suggestions by Mark Hulme.
2006.05.05 [2.2.0] added "linkedbg" handling to set background color when a 'dated tiddler' exists. Based on a suggestion by Mark Hulme.
2006.03.08 [2.1.2] add 'override leadtime' flag param in call to findTiddlersWithReminders(), and add "Enter a title" default text to new reminder handler. Thanks to Jeremy Sheeley for these additional tweaks.
2006.03.06 [2.1.0] hasReminders() nows uses window.reminderCacheForCalendar[] when present. If calendar cache is not present, indexReminders() now uses findTiddlersWithReminders() with a 90-day look ahead to check for reminders. Also, switched default background colors for autostyled dates: reminders are now greenish ("c0ffee") and holidays are now reddish ("ffaace").
2006.02.14 [2.0.5] when readOnly is set (by TW core), omit "new reminders..." popup menu item and, if a "dated tiddler" does not already exist, display the date as simple text instead of a link.
2006.02.05 [2.0.4] added var to variables that were unintentionally global. Avoids FireFox 1.5.0.1 crash bug when referencing global variables
2006.01.18 [2.0.3] In 1.2.x the tiddler editor's text area control was given an element ID=("tiddlerBody"+title), so that it was easy to locate this field and programmatically modify its content. With the addition of configuration templates in 2.x, the textarea no longer has an ID assigned. To find this control we now look through all the child nodes of the tiddler editor to locate a "textarea" control where attribute("edit") equals "text", and then append the new reminder to the contents of that control.
2006.01.11 [2.0.2] correct 'weekend' override detection logic in showDate()
2006.01.10 [2.0.1] allow custom-defined weekend days (default defined in config.macros.date.weekend[] array)
added flag param to showDate() API to override internal weekend[] array
2005.12.27 [2.0.0] Update for TW2.0
Added parameter handling for 'linkformat'
2005.12.21 [1.2.2] FF's date.getYear() function returns 105 (for the current year, 2005). When calculating a date value from Y M and D expressions, the plugin adds 1900 to the returned year value get the current year number. But IE's date.getYear() already returns 2005. As a result, plugin calculated date values on IE were incorrect (e.g., 3905 instead of 2005). Adding +1900 is now conditional so the values will be correct on both browsers.
2005.11.07 [1.2.1] added support for "tiddler" dynamic date parameter
2005.11.06 [1.2.0] added support for "tiddler:title" dynamic date parameter
2005.11.03 [1.1.2] when a reminder doesn't have a specified title parameter, use the title of the tiddler that contains the reminder as "fallback" text in the popup menu. Based on a suggestion from BenjaminKudria.
2005.11.03 [1.1.1] Temporarily bypass hasReminders() logic to avoid excessive overhead from generating the indexReminders() cache. While reminders can still appear in the popup menu, they just won't be indicated by auto-styling the date number that is displayed. This single change saves approx. 60% overhead (5 second delay reduced to under 2 seconds).
2005.11.01 [1.1.0] corrected logic in hasModifieds() and hasReminders() so caching of indexed modifieds and reminders is done just once, as intended. This should hopefully speed up calendar generators and other plugins that render multiple dates...
2005.10.31 [1.0.1] documentation and code cleanup
2005.10.31 [1.0.0] initial public release
2005.10.30 [0.9.0] pre-release
<<<
Claude Shannon invented information theory in 1948 and it forms the basis for the design of all modern day communication systems. His original theory was primarily point-to-point, quantifying information and studying how fast it can flow across an isolated noisy communication channel. Until recently, there has been only limited success in extending the theory to a network of interacting nodes. Progress has been made in the past decade, driven both by engineering interest in wireless networks as well as conceptual advances such as network coding, which shows the surprising result that even in noiseless wireline networks, coding across packets can improve throughput beyond pure store-and-forward routing.
There are three main distinguishing features of wireless medium: channel strength, broadcast and superposition. Because of these effects, links in a wireless network are never isolated but instead interact in seemingly complex ways. Our strategy is to use analytically simpler discrete deterministic network models to capture the interaction between nodes in wireless networks and as an approximation to more complex noisy network models. Our methodology is pictorially shown below.
{{textcenter{
[img(60%,auto)[./figs/methodology.jpg]]
}}}
Now we briefly introduce the @@color(darkblue): ''linear deterministic model''@@ and illustrate how we can deterministically model three key features of a wireless channel.
!!Modeling Signal Strength
Consider the real scalar Gaussian model for point to point link, y=hx+z, where z~N(0,1). There is also an average power constraint equal to one at the transmitter. The transmit power and noise power are both normalized to be equal to 1 and the signal-to-noise ratio (SNR) is captured in terms of channel gains. So h is a fixed real number representing the channel gain (signal strength), and |h|^^2^^=SNR. It is well known that the capacity of this point-to-point channel is C~~AWGN~~ =1/2 log(1+SNR). To get an intuitive understanding of this capacity formula let us write the received signal in y, in terms of the binary expansions of x and z. For simplicity assume x and z are positive real numbers and z has a peal power equal to 1, then we have
{{textcenter{
y= 2^^1/2 log SNR^^ ∑~~i>0~~x(i)2^^-i^^ + ∑~~i>0~~z(i)2^^-i^^
}}}
Therefore think of transmitted signal $x$ as a sequence of bits at different signal levels, with the highest signal level in x being the most significant bit (MSB) and the lowest level being the least significant bit (LSB). Now we can intuitively model a point-to-point Gaussian channel as a pipe that truncates the transmitted signal and only passes the bits that are above the noise level. In the simplified model the receiver can see the n most significant bits of x without any noise and the rest are not seen at all. Clearly there is a correspondence between n and SNR in dB scale, n → ⌈ 1/2 log SNR ⌉^^+^^.
[>img(40%,auto)[./figs/p2p.jpg]]
As we notice in this simplified model there is no background noise any more and hence it is a @@color(darkblue): deterministic model@@. Pictorially the deterministic model corresponding to the AWGN channel is shown on right. In this figure, at the transmitter there are several small circles. Each circle represents a signal level and a binary digit can be put for transmission at each signal level. Depending on n, which represents the channel gain in dB scale, the transmitted bits at the first n signal levels will be received clearly at the destination. However the bits at other signal levels will not go through the channel.
These signal levels can potentially be created by using a multi-level lattice code in the AWGN channel. Then the first n levels in the deterministic model represent those levels (in the lattice chain) that are above noise level, and the remaining are the ones that are below noise level. Therefore, if we think of the transmit signal, ''x'', as a binary vector of length q, then the deterministic channel delivers only its first n bits to the destination. We can algebraically write this input-output relationship by shifting ''x'' down by q-n elements or more precisely, ''y''=''S''^^q-n^^''x'', where ''x'' and ''y'' are binary vectors of length q denoting transmit and received signals respectively and ''S'' is the q×q [[shift matrix|http://en.wikipedia.org/wiki/Shift_matrix]]. Clearly the capacity of this deterministic point-to-point channel is n, where n=⌈1/2 log SNR⌉^^+^^. It is interesting to note that this is a within 0.5-bit approximation of the capacity of the AWGN channel. In the case of complex Gaussian channel we set n=⌈log SNR⌉^^+^^ and we get a within 1-bit approximation of the capacity.
!!Modeling Broadcast
Based on the intuition obtained so far, it is straightforward to think of a deterministic model for a broadcast scenario. Consider the real scalar Gaussian broadcast channel. Assume there are only two receivers. The received SNR at receiver i is denoted by SNR~~i~~ for i=1,2. Without loss of generality assume SNR~~2~~ ≤ SNR~~1~~. Consider the binary expansion of the transmitted signal, x. Then we can deterministically model the Gaussian broadcast channel as the following:
*Receiver 2 (weak user) receives only the first n~~2~~ bits in the binary expansion of x. Those bits are the ones that arrive above the noise level.
*Receiver 1 (strong user) receives the first n~~1~~ (n~~1~~>n~~2~~) bits in the binary expansion of x. Clearly these bits contain what receiver 1 gets.
The deterministic model in some sense abstracts away the use of superposition coding and successive interference cancellation decoding in the Gaussian broadcast channel. Therefore the first n~~2~~ levels in the deterministic model represent the cloud center that is decoded by both users, and the remaining n~~1~~-n~~2~~ levels represent the cloud detail that is decoded only by the strong user (after decoding the cloud center and canceling it from the received signal).
[>img(60%,auto)[./figs/bc.jpg]]
Pictorially the deterministic model for a Gaussian broadcast channel is shown in figure (a) on the right. In this particular example n~~1~~=5 and n~~2~~=2, therefore both users receive the first two most significant bits of the transmitted signal. However user 1 (strong user) receives additional three bits from the next three signal levels of the transmitted signal. There is also the same correspondence between n and channel gains in dB.
To analytically demonstrate how closely we are modeling the Gaussian BC channel, the capacity region of Gaussian BC channel and deterministic BC channel are shown in Figure (b) with red and blue colors respectively. As it is seen their capacity regions are very close to each other. In fact it is easy to verify that for all SNR's these regions are always within one bit per user of each other. However, this is only the worst case gap and in a typical case that SNR~~1~~ and SNR~~2~~ are very different the gap is much smaller than one bit.
!!Modeling Superposition
Consider a superposition scenario in which two users are simultaneously transmitting to a node. In the Gaussian model the received signal can be written as, y=h_1 x_1+h_2 x_2+z. Without loss of generality assume SNR~~2~~<SNR~~1~~. Then based on the intuition obtained from the point-to-point and broadcast AWGN channels, we can approximately model this as the following:
*Those bits in the binary expansion of x~~1~~ that are received above SNR~~2~~, are received clearly without any interaction from x~~2~~.
*The remaining part of x~~1~~ that isreceived above noise level and that part of x~~2~~ that is received above noise level interact with each other and are received without any noise.
*Those parts of x~~1~~ and x~~2~~ that are below noise level are truncated and not received at all.
[>img(60%,auto)[./figs/mac.jpg]]
The key point is how to model the interaction between the bits that are received at the same signal level. In our deterministic model we ignore the carry-overs of the real addition and we model the interaction by the modulo 2 sum of the bits that are arrived at the same signal level. Pictorially the deterministic model for a Gaussian MAC channel is shown in Figure (a) on right. Analogous to the deterministic model for the point-to-point channel, we can write
{{textcenter{
''y''=''S''^^q-n~~1~~^^''x~~1~~''⊕''S''^^q-n~~1~~^^''x~~1~~''
}}} where the summation is in ''F~~2~~'' (modulo 2). Here ''x~~i~~'' (i=1,2) and ''y'' are binary vectors of length q$ enoting transmit and received signals respectively and ''S'' is a q×q shift matrix. To analytically demonstrate how closely we are modeling the Gaussian MAC channel, the capacity region of Gaussian MAC channel and deterministic MAC channel are shown in Figure (b) with red and blue colors respectively. As it is seen their capacity regions are very close to each other. In fact it is easy to verify that for all SNR's these regions are always within one bit per user of each other.
!!Linear Finite Field Deterministic Model
Now we can define the linear finite-field deterministic model for general networks. In the linear finite-field deterministic model the communication link from node i to node j has a non-negative integer gain n~~(i,j)~~ associated with it. This number models the channel gain in a corresponding Gaussian setting. At each time t, node i transmits a vector ''x~~i~~''[t]∈''F''~~p~~^^q^^ and receives a vector ''y''~~i~~[t]∈''F''~~p~~^^q^^ where q=max~~i,j~~(n~~(i,j)~~) and p is a positive integer indicating the field size. The received signal at each node is a deterministic function of the transmitted signals at the other nodes, with the following input-output relation: if the nodes in the network transmit ''x''~~1~~[t], ''x''~~2~~[t] ,...,''x''~~N~~[t] then the received signal at node j, 1≤j≤N is:
{{textcenter{
''y''~~j~~[t]=∑~~i~~''S''^^q-n~~(i,j)~~^^''x''~~i~~[t]
}}} where the summations and the multiplications are in ''F''~~p~~.
/***
|!''Name:''|!''E''asily ''A''daptable ''S''ource ''E''ditor|
|''Description:''|this framework allows you to easily create commands that work on the current tiddler text selection in edit mode|
|''Version:''|0.1.0|
|''Date:''|13/01/2007|
|''Source:''|http://yann.perrin.googlepages.com/twkd.html#E.A.S.E|
|''Author:''|[[Yann Perrin|YannPerrin]]|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.x|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
***/
////Messages Definition
//{{{
config.messages.Ease = {
noselection:"nothing selected",
asktitle:"enter the new tiddler title",
exists:" already exists, please enter another title",
askForTagsLabel:"enter the new tiddler tags",
tiddlercreated:" tiddler created"
}
//}}}
////
//{{{
if (!window.TWkd) window.TWkd={context:{}};
if (!TWkd.Ease)
TWkd.Ease = function (text,tooltip){
this.text = text;
this.tooltip = tooltip;
this.modes = [];
this.addMode = function(modeDefinition) {this.modes.push(modeDefinition);};
this.handler = function(event,src,title) {
TWkd.context.command = this;
TWkd.context.selection=this.getSelection(title);
if (this.modes.length==1) {
this.modes[0].operation();
}
else {
var popup = Popup.create(src);
if(popup) {
for (var i=0; i<this.modes.length; i++) {
createTiddlyButton(createTiddlyElement(popup,"li"), this.modes[i].name, this.modes[i].tooltip, this.OperateFromButton, null, 'id'+i, null);
}
Popup.show(popup,false);
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
};
};
TWkd.Ease.prototype.OperateFromButton = function(e){
var commandMode=this.getAttribute('Id').replace('id','');
TWkd.context.command.modes[commandMode].operation();
};
TWkd.Ease.prototype.getTiddlerEditField = function(title,field){
var tiddler = document.getElementById(story.idPrefix + title);
if(tiddler != null){
var children = tiddler.getElementsByTagName("*")
var e = null;
for (var t=0; t<children.length; t++){
var c = children[t];
if(c.tagName.toLowerCase() == "input" || c.tagName.toLowerCase() == "textarea"){
if(!e) {e = c;}
if(c.getAttribute("edit") == field){e = c;}
}
}
if(e){return e;}
}
} // closes getTiddlerEditField function definition
TWkd.Ease.prototype.getSelection = function(title,quiet) {
var tiddlerTextArea = this.getTiddlerEditField(title,"text");
var result = {};
if (document.selection != null && tiddlerTextArea.selectionStart == null) {
tiddlerTextArea.focus();
var range = document.selection.createRange();
var bookmark = range.getBookmark();
var contents = tiddlerTextArea.value;
var originalContents = contents;
var marker = "##SELECTION_MARKER_" + Math.random() + "##";
while(contents.indexOf(marker) != -1) {
marker = "##SELECTION_MARKER_" + Math.random() + "##";
}
var selection = range.text;
range.text = marker + range.text + marker;
contents = tiddlerTextArea.value;
result.start = contents.indexOf(marker);
contents = contents.replace(marker, "");
result.end = contents.indexOf(marker);
tiddlerTextArea.value = originalContents;
range.moveToBookmark(bookmark);
range.select();
}
else {
result.start=tiddlerTextArea.selectionStart;
result.end=tiddlerTextArea.selectionEnd;
}
result.content=tiddlerTextArea.value.substring(result.start,result.end);
result.source=title;
if (!result.content&&!quiet) displayMessage(config.messages.Ease.noselection);
return(result);
}//closes getSelection function definition
// replace selection or insert new content
TWkd.Ease.prototype.putInPlace=function(content,workplace) {
var tiddlerText = this.getTiddlerEditField(workplace.source,"text");
tiddlerText.value = tiddlerText.value.substring(0,workplace.start)+content+tiddlerText.value.substring(workplace.end);
}
// asking for title
TWkd.Ease.prototype.askForTitle = function(suggestion) {
if (!suggestion)
suggestion = "";
var newtitle;
while (!newtitle||store.tiddlerExists(newtitle))
{
if (store.tiddlerExists(newtitle))
displayMessage(newtitle+config.messages.Ease.exists);
newtitle = prompt(config.messages.Ease.asktitle,suggestion);
if (newtitle==null)
{
displayMessage(config.messages.Ease.titlecancel);
return(false);
}
}
return(newtitle);
}//closes askForTitle function definition
// creation of a new tiddler
TWkd.Ease.prototype.newTWkdLibTiddler = function(title,content,from,askForTags){
var tiddler = new Tiddler();
tiddler.title = title;
tiddler.modifier = config.options.txtUserName;
tiddler.text = content;
(from) ? tiddler.tags = [from] : tiddler.tags=[];
if (askForTags)
tiddler.tags = prompt(config.messages.Ease.askForTagsLabel,'[['+from+']]').readBracketedList();
store.addTiddler(tiddler);
//store.notifyAll();
displayMessage(title+config.messages.Ease.tiddlercreated);
}
if (!TWkd.Mode)
TWkd.Mode = function (name,tooltip,ask,operation) {
this.name = name;
this.tooltip = tooltip;
this.ask = ask;
this.operation = operation;
};
//}}}
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='editor' macro='edit title'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
{{firstletter{
@@color:gray;I@@
}}} am presently a postdoctoral scholar in the [[Center for the Mathematics of Information|http://www.cmi.caltech.edu]] at [[Caltech|http://www.caltech.edu/]]. This summer I will be joining the [[School of Electrical and Computer Engineering|http://www.ece.cornell.edu/]] at [[Cornell University|http://www.cornell.edu/]] as an assistant professor. For my research interests and publications take a look [[here|Research interests]] and [[here|Publications]].
I was previously a member of [[Wireless Foundations|http://www.eecs.berkeley.edu/wireless/]] in the [[EECS department|http://www.eecs.berkeley.edu/]] of [[UC Berkeley|http://www.berkeley.edu]], where I received my Ph.D. and M.Sc. in 2008 and 2005 respectively. My doctoral dissertation was supervised by professor [[David Tse|http://www.eecs.berkeley.edu/~dtse/]]. I received my B.Sc. from the [[EE department|http://www.ee.sharif.edu/]] of [[Sharif University of Technology|http://sharif.edu]] in 2003.
I have received a number of rewards including the [[David J. Sakrison Memorial Prize|http://www.eecs.berkeley.edu/Students/Awards/#sakrison]] for the most outstanding doctoral research in the EECS department of UC Berkeley in 2008. I also received the Vodafone U.S. Foundation Fellows Initiative Research Merit Award in 2005.
/***
|Name|ImageSizePlugin|
|Source|http://www.TiddlyTools.com/#ImageSizePlugin|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin,formatter|
|Requires||
|Overrides|'image' formatter|
|Description|extends image syntax to add optional CSS width/height values|
!!!!!Usage
<<<
Extends standard TiddlyWiki image syntax, ''{{{[img[...]]}}}'', so you can specify CSS width/height values.
The extended syntax is:
>''{{{[img(x,y)[...]]}}}''
>where x and y are the desired width and height of the image, specified using CSS units of measurement (e.g., px, em, cm, in, or %). Use ''auto'' for either the width or height to scale image proportionally (i.e., maintain aspect ratio). You may also calculate a CSS value on-the-fly by using //evaluated javascript//, enclosed between """{{""" and """}}""", e.g, {{{({{widthFunction()}},{{heightFunction()}})}}}.
Note: this plugin also includes enhancements to support:
*[[AttachFilePluginFormatters]] (embed image files as text-encoded tiddlers)
* [[ImagePathPlugin]] (fallback locations for missing images)
Please refer to those plugins for details...
<<<
!!!!!Examples
<<<
{{{
[<img(34%,auto)[images/meow.gif]]
[<img(21%,auto)[images/meow.gif]]
[<img(13%,auto)[images/meow.gif]]
[<img(8%,auto)[images/meow.gif]]
[<img(5%,auto)[images/meow.gif]]
[<img(3%,auto)[images/meow.gif]]
[<img(2%,auto)[images/meow.gif]]
[img(1%,auto)[images/meow.gif]]
}}}
[<img(34%,auto)[images/meow.gif]]
[<img(21%,auto)[images/meow.gif]]
[<img(13%,auto)[images/meow.gif]]
[<img(8%,auto)[images/meow.gif]]
[<img(5%,auto)[images/meow.gif]]
[<img(3%,auto)[images/meow.gif]]
[<img(2%,auto)[images/meow.gif]]
[img(1%,auto)[images/meow.gif]]
{{clear block{}}}
<<<
!!!!!Revisions
<<<
2008.01.19 [1.1.0] added support for evaluated width/height values!!
2008.01.18 [1.0.1] code cleanup plus improved regexp for matching "(width,height)" by eliminating hard-coded recognition of [px,em,cm,in,%] CSS units. Syntax now accepts ANY values for width/height, and leaves it to the browser's CSS processing to handle any invalid values.
2008.01.17 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.ImageSizePlugin= {major: 1, minor: 1, revision: 0, date: new Date(2008,1,19)};
// replace standard handler for image formatter
// note: includes modifications for [[AttachFilePluginFormatters]] AND [[ImagePathPlugin]]
var f=config.formatters.findByField("name","image");
config.formatters[f].match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
config.formatters[f].lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](\([^,]*,[^\)]*\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
config.formatters[f].handler=function(w) {
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var floatLeft=lookaheadMatch[1];
var floatRight=lookaheadMatch[2];
var XY=lookaheadMatch[3];
var tooltip=lookaheadMatch[4];
var src=lookaheadMatch[5];
var link=lookaheadMatch[6];
// Simple bracketted link
var e = w.output;
if(link) { // LINKED IMAGE
if (config.formatterHelpers.isExternalLink(link)) {
if (config.macros.attach && config.macros.attach.isAttachment(link)) {
// see [[AttachFilePluginFormatters]]
e = createExternalLink(w.output,link);
e.href=config.macros.attach.getAttachment(link);
e.title = config.macros.attach.linkTooltip + link;
} else
e = createExternalLink(w.output,link);
} else
e = createTiddlyLink(w.output,link,false,null,w.isStatic);
addClass(e,"imageLink");
}
var img = createTiddlyElement(e,"img");
if(floatLeft) img.align="left"; else if(floatRight) img.align="right"; // FLOAT LEFT/RIGHT
if(XY) { // CUSTOM SIZE with optional EVAL'ED width/height ({{...}},{{...}})
var parts=XY.replace(/[\(\)]/g,'').split(","); var x=parts[0]; var y=parts[1];
if (x.substr(0,2)=="{{") {
try{img.style.width=eval(x.substr(2,x.length-4));}
catch(e){displayMessage(e.description||e.toString())}
} else img.style.width=x;
if (y.substr(0,2)=="{{") {
try{img.style.height=eval(y.substr(2,y.length-4));}
catch(e){displayMessage(e.description||e.toString())}
} else img.style.height=y;
}
if(tooltip) img.title = tooltip; // TOOLTIP
// GET IMAGE SOURCE (get attachment or resolve fallback path as needed)
if (config.macros.attach && config.macros.attach.isAttachment(src))
src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
// Note: IE and Safari use onError to call resolvePath() only if initial lookup fails
// (avoids security messages for initial filesystem access)... otherwise, attempt to
// resolve the original path/file before initial rendering
if (config.browser.isIE || config.browser.isSafari) {
img.onerror=(function(){
this.src=config.formatterHelpers.resolvePath(this.src,false);
return false;
});
} else
src=config.formatterHelpers.resolvePath(lookaheadMatch[5],true);
}
img.src=src; // RENDER IMAGE
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
//}}}
[[Home]]
<<slider chkSlide [[ResearchItems]] Research>>
[[Teaching]]
[[Calendar of Events]]
[[Prospective students]]
[[Contact]]
<!--{{{-->
<div id='header'>
</div>
<div id='sidebar'>
<div id='titleLine'></div>
<span id='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<!--- <span id='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>-->
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
/***
|Name|Plugin: arXiv Links|
|Created by|BobMcElrath|
|Email|my first name at my last name dot org|
|Location|http://bob.mcelrath.org/tiddlyjsmath-2.0.3.html|
|Version|1.0|
|Requires|[[TiddlyWiki|http://www.tiddlywiki.com]] ≥ 2.0.3|
!Description
This formatting plugin will render links to the [[arXiv|http://www.arxiv.org]] preprint system. If you type a paper reference such as hep-ph/0509024, it will be rendered as an external link to the abstract of that paper.
!Installation
Add this tiddler to your tiddlywiki, and give it the {{{systemConfig}}} tag.
!History
* 1-Feb-06, version 1.0, Initial release
!Code
***/
//{{{
config.formatters.push({
name: "arXivLinks",
match: "\\b(?:astro-ph|cond-mat|hep-ph|hep-th|hep-lat|gr-qc|nucl-ex|nucl-th|quant-ph|(?:cs|math|nlin|physics|q-bio)(?:\\.[A-Z]{2})?)/[0-9]{7}\\b",
element: "a",
handler: function(w) {
var e = createExternalLink(w.output, "http://arxiv.org/abs/"+w.matchText);
e.target = "_blank"; // open in new window
w.outputText(e,w.matchStart,w.nextMatch);
}
});
//}}}
/***
|Name|Plugin: jsMath|
|Created by|BobMcElrath|
|Email|my first name at my last name dot org|
|Location|http://bob.mcelrath.org/tiddlyjsmath.html|
|Version|1.5.1|
|Requires|[[TiddlyWiki|http://www.tiddlywiki.com]] ≥ 2.0.3, [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]] ≥ 3.0|
!Description
LaTeX is the world standard for specifying, typesetting, and communicating mathematics among scientists, engineers, and mathematicians. For more information about LaTeX itself, visit the [[LaTeX Project|http://www.latex-project.org/]]. This plugin typesets math using [[jsMath|http://www.math.union.edu/~dpvc/jsMath/]], which is an implementation of the TeX math rules and typesetting in javascript, for your browser. Notice the small button in the lower right corner which opens its control panel.
!Installation
In addition to this plugin, you must also [[install jsMath|http://www.math.union.edu/~dpvc/jsMath/download/jsMath.html]] on the same server as your TiddlyWiki html file. If you're using TiddlyWiki without a web server, then the jsMath directory must be placed in the same location as the TiddlyWiki html file.
I also recommend modifying your StyleSheet use serif fonts that are slightly larger than normal, so that the math matches surrounding text, and \\small fonts are not unreadable (as in exponents and subscripts).
{{{
.viewer {
line-height: 125%;
font-family: serif;
font-size: 12pt;
}
}}}
If you had used a previous version of [[Plugin: jsMath]], it is no longer necessary to edit the main tiddlywiki.html file to add the jsMath <script> tag. [[Plugin: jsMath]] now uses ajax to load jsMath.
!History
* 11-Nov-05, version 1.0, Initial release
* 22-Jan-06, version 1.1, updated for ~TW2.0, tested with jsMath 3.1, editing tiddlywiki.html by hand is no longer necessary.
* 24-Jan-06, version 1.2, fixes for Safari, Konqueror
* 27-Jan-06, version 1.3, improved error handling, detect if ajax was already defined (used by ZiddlyWiki)
* 12-Jul-06, version 1.4, fixed problem with not finding image fonts
* 26-Feb-07, version 1.5, fixed problem with Mozilla "unterminated character class".
* 27-Feb-07, version 1.5.1, Runs compatibly with TW 2.1.0+, by Bram Chen
!Examples
|!Source|!Output|h
|{{{The variable $x$ is real.}}}|The variable $x$ is real.|
|{{{The variable \(y\) is complex.}}}|The variable \(y\) is complex.|
|{{{This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.}}}|This \[\int_a^b x = \frac{1}{2}(b^2-a^2)\] is an easy integral.|
|{{{This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.}}}|This $$\int_a^b \sin x = -(\cos b - \cos a)$$ is another easy integral.|
|{{{Block formatted equations may also use the 'equation' environment \begin{equation} \int \tan x = -\ln \cos x \end{equation} }}}|Block formatted equations may also use the 'equation' environment \begin{equation} \int \tan x = -\ln \cos x \end{equation}|
|{{{Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} }}}|Equation arrays are also supported \begin{eqnarray} a &=& b \\ c &=& d \end{eqnarray} |
|{{{I spent \$7.38 on lunch.}}}|I spent \$7.38 on lunch.|
|{{{I had to insert a backslash (\\) into my document}}}|I had to insert a backslash (\\) into my document|
!Code
***/
//{{{
// AJAX code adapted from http://timmorgan.org/mini
// This is already loaded by ziddlywiki...
if(typeof(window["ajax"]) == "undefined") {
ajax = {
x: function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}},
gets: function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText}
}
}
// Load jsMath
jsMath = {
Setup: {inited: 1}, // don't run jsMath.Setup.Body() yet
Autoload: {root: new String(document.location).replace(/[^\/]*$/,'jsMath/')} // URL to jsMath directory, change if necessary
};
var jsMathstr;
try {
jsMathstr = ajax.gets(jsMath.Autoload.root+"jsMath.js");
} catch(e) {
alert("jsMath was not found: you must place the 'jsMath' directory in the same place as this file. "
+"The error was:\n"+e.name+": "+e.message);
throw(e); // abort eval
}
try {
window.eval(jsMathstr);
} catch(e) {
alert("jsMath failed to load. The error was:\n"+e.name + ": " + e.message + " on line " + e.lineNumber);
}
jsMath.Setup.inited=0; // allow jsMath.Setup.Body() to run again
// Define wikifers for latex
config.formatterHelpers.mathFormatHelper = function(w) {
var e = document.createElement(this.element);
e.className = this.className;
var endRegExp = new RegExp(this.terminator, "mg");
endRegExp.lastIndex = w.matchStart+w.matchLength;
var matched = endRegExp.exec(w.source);
if(matched) {
var txt = w.source.substr(w.matchStart+w.matchLength,
matched.index-w.matchStart-w.matchLength);
if(this.keepdelim) {
txt = w.source.substr(w.matchStart, matched.index+matched[0].length-w.matchStart);
}
e.appendChild(document.createTextNode(txt));
w.output.appendChild(e);
w.nextMatch = endRegExp.lastIndex;
}
}
config.formatters.push({
name: "displayMath1",
match: "\\\$\\\$",
terminator: "\\\$\\\$\\n?", // 2.0 compatability
termRegExp: "\\\$\\\$\\n?",
element: "div",
className: "math",
handler: config.formatterHelpers.mathFormatHelper
});
config.formatters.push({
name: "inlineMath1",
match: "\\\$",
terminator: "\\\$", // 2.0 compatability
termRegExp: "\\\$",
element: "span",
className: "math",
handler: config.formatterHelpers.mathFormatHelper
});
var backslashformatters = new Array(0);
backslashformatters.push({
name: "inlineMath2",
match: "\\\\\\\(",
terminator: "\\\\\\\)", // 2.0 compatability
termRegExp: "\\\\\\\)",
element: "span",
className: "math",
handler: config.formatterHelpers.mathFormatHelper
});
backslashformatters.push({
name: "displayMath2",
match: "\\\\\\\[",
terminator: "\\\\\\\]\\n?", // 2.0 compatability
termRegExp: "\\\\\\\]\\n?",
element: "div",
className: "math",
handler: config.formatterHelpers.mathFormatHelper
});
backslashformatters.push({
name: "displayMath3",
match: "\\\\begin\\{equation\\}",
terminator: "\\\\end\\{equation\\}\\n?", // 2.0 compatability
termRegExp: "\\\\end\\{equation\\}\\n?",
element: "div",
className: "math",
handler: config.formatterHelpers.mathFormatHelper
});
// These can be nested. e.g. \begin{equation} \begin{array}{ccc} \begin{array}{ccc} ...
backslashformatters.push({
name: "displayMath4",
match: "\\\\begin\\{eqnarray\\}",
terminator: "\\\\end\\{eqnarray\\}\\n?", // 2.0 compatability
termRegExp: "\\\\end\\{eqnarray\\}\\n?",
element: "div",
className: "math",
keepdelim: true,
handler: config.formatterHelpers.mathFormatHelper
});
// The escape must come between backslash formatters and regular ones.
// So any latex-like \commands must be added to the beginning of
// backslashformatters here.
backslashformatters.push({
name: "escape",
match: "\\\\.",
handler: function(w) {
w.output.appendChild(document.createTextNode(w.source.substr(w.matchStart+1,1)));
w.nextMatch = w.matchStart+2;
}
});
config.formatters=backslashformatters.concat(config.formatters);
window.wikify = function(source,output,highlightRegExp,tiddler)
{
if(source && source != "") {
if(version.major == 2 && version.minor > 0) {
var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
wikifier.subWikifyUnterm(output);
} else {
var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler);
wikifier.subWikify(output,null);
}
jsMath.ProcessBeforeShowing();
}
}
//}}}
!!Recent talks
{{alignBullets {
*@@color(darkblue):"Information flow over wireless networks: a deterministic approach"@@, given at Cornell, Caltech, UIUC, etc. [[slides|./papers/DetApproachSlides.pdf]]
*@@color(darkblue):"Diversity multiplexing tradeoff of the half-duplex relay channel"@@, Allerton 2008. [[slides|./papers/DMTRelaySlides.pdf]]
*@@color(darkblue):"Approximate capacity of the two-way relay channel: a deterministic approach"@@, Allerton 2008. [[slides|./papers/TWRSlides.pdf]]
*@@color(darkblue):"Approximate capacity of Gaussian relay networks"@@, ISIT 2008. [[slides|./papers/APPRelaySlides.pdf]]
*@@color(darkblue):"A deterministic approach to wireless relay networks"@@, Allerton 2007. [[slides|./papers/Allerton071Slides.pdf]]
*@@color(darkblue):"Cooperative Protocols for the Relay Channel at Low SNR"@@, WICAT. [[slides|./papers/wicatSlides.ppt]]
*@@color(darkblue):"Outage Optimal Relaying in the Low SNR Regime"@@, ISIT 2005. [[slides|./papers/RelayOutageSlides.pdf]]
*@@color(darkblue):"Cooperative Relaying"@@, Qualcomm 2005. [[slides|./papers/coopSlides.pdf]]
}}}
Cornell is a wonderful place to pursue studies and experience the exitement of discovering new ideas.
I am currently planning to take a few graduate students with strong mathematical background. If you are admitted to Cornell and would like to find out about my research interests you can have a look at some of my [[publications|Publications]] and [[talk slides|Presentations]]. If you want to learn more, please contact me. If you are planning to apply to Cornell and are interested in my research, please mention this in your application package.
!!Selected Publications
*''//@@color(green):(NEW)@@//'' @@color(darkblue):"On Networks with Side Information "@@, A. Cohen, S. Avestimehr and M. Effors, will be presented at ISIT 2009 in Seoul, Korea, June 28-July 3, 2009. @@color(lightgreen):will be uploaded soon ...@@
@@color(gray):Abstract: In this paper, we generalize the lossless coded side information problem from the three-node network of Ahlswede and Korner to more general network scenarios. We derive inner and outer bounds on the achievable rate region in the general network scenario and show that they are tight for some example networks. @@
*''//@@color(green):(NEW)@@//'' @@color(darkblue):"Approximate capacity region of the two-pair bidirectional Gaussian relay network "@@, A. Sezgin, M. Khajehnejad, S. Avestimehr and B. Hassibi, will be presented at ISIT 2009 in Seoul, Korea, June 28-July 3, 2009. @@color(lightgreen):will be uploaded soon ...@@
@@color(gray):Abstract: We study the capacity of the Gaussian two-pair full-duplex directional (or two-way) relay network with a single-relay supporting the communication of the pairs. This network is a generalization of the well known bidirectional relay channel, where we have only one pair of users. We propose a novel transmission technique which is based on a specific superposition of lattice codes and random Gaussian codes at the source nodes. The relay attempts to decode the Gaussian codewords and the superposition of the lattice codewords of each pair. Then it forwards this information to all users. We analyze the achievable rate of this scheme and show that for all channel gains it achieves to within 2 bits/sec/Hz per user of the cut-set upper bound on the capacity region of the two-pair bidirectional relay network. @@
*''//@@color(green):(NEW)@@//'' @@color(darkblue):"Weighted $\ell_1$ Minimization for Sparse Recovery with Prior Information "@@, M. Khajehnejad, W. Xu, S. Avestimehr and B. Hassibi, will be presented at ISIT 2009 in Seoul, Korea, June 28-July 3, 2009. @@color(lightgreen):will be uploaded soon ...@@
@@color(gray):Abstract: In this paper we study the compressed sensing problem of recovering a sparse signal from a system of underdetermined linear equations when we have prior information about the probability of each entry of the unknown signal being nonzero. In particular, we focus on a model where the entries of the unknown vector fall into two sets, each with a different probability of being nonzero. We propose a weighted $\ell_1$ minimization recovery algorithm and analyze its performance using a Grassman angle approach. We compute explicitly the relationship between the
system parameters (the weights, the number of measurements, the size of the two sets, the probabilities of being non-zero) so that an iid random Gaussian measurement matrix along with weighted $\ell_1$ minimization recovers almost all such sparse signals with overwhelming probability as the problem dimension increases. This allows us to compute the optimal weights. We also provide simulations to demonstrate the advantages of the method over conventional $\ell_1$ optimization. @@
*''//@@color(green):(NEW)@@//'' @@color(darkblue):"Approximate capacity of the symmetric half-duplex Gaussian butterfly network "@@, S. Avestimehr and T. Ho, will be presented at ITW 2009 in Volos, Greece, June 10-12, 2009. [[PDF|./papers/wirelessButterflyITW09.pdf]]
@@color(gray):Abstract: In this paper we study the capacity of the half-duplex wireless butterfly network, in which a relay node facilitates the communication between two interfering transmitter-receiver pairs. We use the deterministic approach to make progress towards approximating the capacity region of this network. We use the insights obtained from the analysis of the corresponding deterministic problem to derive a new upper bound on the capacity of this network. We also propose a transmission strategy and show that for symmetric channel gains the gap between its achievable rate region and the upper bound is at most (log 15)/2 ≈ 1.95 bits/sec/Hz per user. @@
*''//@@color(green):(NEW)@@//'' @@color(darkblue):"Capacity region of the deterministic multi-pair bi-directional relay network"@@, S. Avestimehr, A. Khajehnejad, A. Sezgin, and B. Hassibi, will be presented at ITW 2009 in Volos, Greece, June 10-12, 2009. [[PDF|./papers/AKSH-ITW09.pdf]]
@@color(gray):Abstract: In this paper we study the capacity region of the multi-pair bidirectional (or two-way) wireless relay network, in which a relay node facilitates the communication between multiple pairs of users. This network is a generalization of the well known bidirectional relay channel, where we have only one pair of users. We examine this problem in the context of the deterministic channel interaction model, which eliminates the channel noise and allows us to focus on the interaction between signals. We characterize the capacity region of this network when the relay is operating at either full-duplex mode or half-duplex mode (with non adaptive listen-transmit scheduling). In both cases we show that the cut-set upper bound is tight and, quite interestingly, the capacity region is achieved by a simple equation-forwarding strategy. @@
*@@color(darkblue):"Wireless network information flow: a deterministic approach"@@, Salman Avestimehr, Suhas Diggavi and David Tse, preprint.
@@color(gray):Abstract: In contrast to wireline networks, not much is known about the flow of information over wireless networks. The main barrier is the complexity of the interaction models that are commonly used for wireless channels, such as the additive Gaussian channel model. In this paper, we present a deterministic approach to this problem. We propose a deterministic channel model which is analytically simpler than the Gaussian model but still captures two key wireless channels: broadcast and superposition. The noiseless nature of this allows us to focus on the interaction between signals transmitted from different nodes of the network rather than background noise of the links. We consider a model for a wireless relay network with nodes connected by such deterministic channels, and present an exact characterization of the end-to-end capacity when there is a single source and a single destination and an arbitrary number of relay (helper) nodes. This result is a natural generalization of the celebrated max-flow min-cut theorem for wireline networks. Next, we use the insights obtained from the analysis of the deterministic model and present an achievable rate for general Gaussian relay networks. We show that the achievable rate is within a constant number of bits from the (unknown) capacity of these networks. This constant depends on the number of nodes in the network, but not the values of the channel gains. Therefore, we uniformly characterize the capacity of Gaussian relay networks within a constant number of bits, for all channel gains. @@
*@@color(darkblue):"Capacity of the two-way relay channel within a constant gap"@@, S. Avestimehr, A. Sezgin, and D. Tse, submitted to European Transactions in Telecommunications, December 2008.
*@@color(darkblue):"Approximate capacity of the two-way relay channel: a deterministic approach"@@, Salman Avestimehr, Aydin Sezgin and David Tse, Proceedings of Allerton Conference on Communication, Control, and computing, Illinois, September 2008. [[PDF|./papers/ASTAllerton08.pdf]]
@@color(gray):Abstract: We study the capacity of the full-duplex bidirectional (or two-way) relay channel with two nodes and one relay. The channels in the forward direction are assumed to be different (in general) than the channels in the backward direction, i.e. channel reciprocity is not assumed. We use the recently proposed deterministic approach to capture the essence of the problem and to determine a good transmission and relay strategy for the Gaussian channel. Depending on the ratio of the individual channel gains, we propose to use either a simple amplify-andforward or a particular superposition coding strategy at the relay. We analyze the achievable rate region and show that the scheme achieves to within 3 bits the cut-set bound for all values of channel gains. @@
*@@color(darkblue):"Diversity multiplexing tradeoff of the half-duplex relay channel"@@, Sameer Pawar, Salman Avestimehr and David Tse, Proceedings of Allerton Conference on Communication, Control, and computing, Illinois, September 2008. (invited paper) [[PDF|./papers/PATAllerton08.pdf]]
@@color(gray):Abstract: We show that the diversity-multiplexing tradeoff of a half-duplex single-relay channel with identically distributed Rayleigh fading channel gains meets the 2 by 1 MISO bound. We generalize the result to the case when there are N non-interfering relays and show that the diversity-multiplexing tradeoff is equal to the N + 1 by 1 MISO bound.@@
*@@color(darkblue):"Approximate capacity of Gaussian relay networks"@@, Salman Avestimehr, Suhas Diggavi and David Tse, a shorter version appeared in the proceedings of ISIT 2008. [[PDF|./papers/ADTISIT08.pdf]]
@@color(gray):Abstract: We present an achievable rate for general Gaussian relay networks. We show that the achievable rate is within a constant number of bits from theinformation-theoretic cut-set upper bound on the capacity of these networks. This constant depends on the topology of thenetwork, but not the values of the channel gains. Therefore, we uniformly characterize the capacity of Gaussian relay networks within a constant number of bits, for all channel parameters. @@
*@@color(darkblue):"Information flow over compound wireless relay networks"@@, Salman Avestimehr, Suhas Diggavi and David Tse, IEEE international Zurich seminar (IZS) 2008. [[PDF|./papers/ADTIZS08.pdf]]
*@@color(darkblue):"Approximate characterization of capacity in Gaussian relay networks"@@, Salman Avestimehr, Suhas Diggavi and David Tse, IEEE International Wireless Communications and Mobile Computing Conference (IWCMC), Crete, August 2008. [[PDF|./papers/ADTIWCMC08.pdf]]
*@@color(darkblue):"A deterministic approach to wireless relay networks"@@, Salman Avestimehr, Suhas Diggavi and David Tse, Proceedings of Allerton Conference on Communication, Control, and computing, Illinois, September 2007 (invited paper). [[PDF|./papers/ADTAllerton071.pdf]]
@@color(gray):Abstract: We present a deterministic channel model which captures several key features of multiuser wireless communication. We consider a model for a wireless network with nodes connected by such deterministic channels , and present an exact characterization of the end-toend capacity when there is a single source and a single destination and an arbitrary number of relay nodes. This result is a natural generalization of the max-flow mincut theorem for wireline networks. Finally to demonstrate the connections between deterministic model and Gaussian model, we look at two examples: the single-relay channel and the diamond network. We show that in each of these two examples, the capacity-achieving scheme in the corresponding deterministic model naturally suggests a scheme in the Gaussian model that is within 1 bit and 2 bit respectively from cut-set upper bound, for all values of the channel gains. This is the first part of a two-part paper, the sequel [1] will focus on the proof of the maxflow min-cut theorem of a class of deterministic networks of which our model is a special case.@@
*@@color(darkblue):"Wireless network information flow"@@, Salman Avestimehr, Suhas Diggavi and David Tse, Proceedings of Allerton Conference on Communication, Control, and computing, Illinois, September 2007 (invited paper). [[PDF|./papers/ADTAllerton072.pdf]]
@@color(gray):Abstract: We present an achievable rate for general deterministic relay networks, with broadcasting at the transmitters and interference at the receivers. In particular we show that if the optimizing distribution for the information-theoretic cut-set bound is a product distribution, then we have a complete characterization of the achievable rates for such networks. For linear deterministic finite-field models discussed in a companion paper [3], this is indeed the case, and we have a generalization of the celebrated max-flow min-cut theorem for such a network.@@
*@@color(darkblue):"A deterministic model for wireless relay networks and its capacity"@@, Salman Avestimehr, Suhas Diggavi and David Tse, IEEE Information Theory Workshop (ITW), Bergen, Norway, pp 6-11, July 2007.
*@@color(darkblue):"Outage Capacity of the Fading Relay Channel in the Low SNR Regime"@@, Salman Avestimehr and David Tse, IEEE Transactions on Information Theory, April 2007, Volume: 53, Issue: 4. [[PDF|./papers/ATIT07.pdf]]
@@color(gray):Abstract: In slow fading scenarios, cooperation between nodes can increase the amount of diversity for communication. We study the performance limit in such scenarios by analyzing the outage capacity of slow fading relay channels. Our focus is on the low SNR and low outage probability regime, where the adverse impact of fading is greatest but so are the potential gains from cooperation. We showed that while the standard Amplify Forward protocol performs very poorly in this regime, a modified version we called the Bursty Amplify Forward protocol is optimal and achieves the outage capacity of the network. Moreover, this performance can be achieved without a priori channel knowledge at the receivers. In contrast, the Decode Forward protocol is strictly sub optimal in this regime. Our results directly yield the outage capacity per unit energy of fading relay channels.@@
**A conference version of this paper appeared in the proceedings of ISIT 2005: [[PDF|./papers/ATISIT05.pdf]]
*@@color(darkblue):"Anytime Communication over the Gilbert Eliot Channel with Noiseless Feedback"@@, Anant Sahai, Salman Avestimehr and Paolo Minero, Proceedings, ISIT 2005, Adelaide, Australia. [[PDF|./papers/SAMISIT05.pdf]]
@@color(gray):Abstract: We study the reliability of sequential codes in a twostate Markov fading AWGN channel under the assumption of noiseless feedback and an average power constraint. We present a capacity achieving scheme with a doubly exponential anytime reliability function with respect to delay for every bit. The scheme is represented by a hybrid control system at the encoder in which the discrete system dynamics evolves based only on the channel state information while the continuous part of the state at the encoder reflects the evolution of the message uncertainty at the decoder. Whereas the classical Schalkwijk Kailath scheme achieves double exponential reliability by exploiting the average nature of the power constraint to combat atypicality of the AWGN noise, our scheme also uses it to combat atypical fading realizations.@@
*@@color(darkblue):"Multirate Structures for Arbitrary Rate Error Control Coding"@@, Salman Avestimehr, Kambiz Nayebi and Shohreh Kasaei, proceedings ICASSP 2003. [[PDF|./papers/ICASSP03.pdf]]
@@color(gray):(Copyright belongs to the publisher in most cases. The author/authors assert copyright in all other cases.)@@
Type the text for 'Research'
My areas of interest include information theory, the theory of communications and its applications: wireless communication systems and networks; cellular mobile radio networks. I am also interested in networking and communication protocol design.
For more information please take a look at my [[selected publications|Publications]] and [[recent talks|Presentations]].
I have been recently working on developing a [[deterministic approach|Deterministic Approach]] to wireless netowork information theory.
[[Research interests]]
[[Publications]]
[[Presentations]]
[[Theses]]
[[CV]]
|Name|SaveFromWebPluginInfo|
|Source|http://www.TiddlyTools.com/#SaveFromWebPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveFromWebPluginInfo|
|Version|1.3.1|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|documentation for SaveFromWebPlugin|
Normally, when you are viewing a TiddlyWiki document over the web (i.e., not via {{{file://}}}) and you select the "save changes" (or "save to disk") command, an error message is displayed: //__"You need to save this TiddlyWiki to a file before you can save changes."__// This plugin extends the use of {{{<<saveChanges>>}}} so that when you are viewing and/or editing a remote TiddlyWiki document, instead of receiving this somewhat confusing and unhelpful message, you can still click the "save changes" (or "save to disk") command to ''store a copy of the remote document directly onto your local filesystem'', //including any unsaved tiddler changes/additions you have made while working on-line.//
!!!!!Usage
<<<
When you select <<saveChanges>> while viewing a remote document (i.e., a URL starting with http: rather than file:), the plugin first ''retrieves the TiddlyWiki core source code from the original document'' file stored on the remote server. Then, it ''combines that core source with the tiddlers'' contained in the currently loaded document, ''including any changes you have made.''
While the next step //should// be to simply write the merged core+tiddler data directly to your hard drive, certain JavaScript features, such as reading/writing directly to the local filesystem, require expanded "cross-domain" privileges that are normally restricted for use only with ''signed'' scripts. Although some browsers will let you grant filesystem permissions to a remotely-loaded script, this usually involves either a series of popup confirmation messages or manually re-configuring (and/or disabling) your browser's built-in security protections, which often include settings and options that most users find difficult to understand and inconvenient to access.
To avoid these security complications, the "save from web" processing requires just a few additional steps to prepare the modified document and deliver it to your browser: rather than writing the document data directly to the local filesystem, the plugin ''sends the merged core+tiddler data to a small companion script installed on the remote server'' (see savefromweb.php, below). This simple "reflector" script then immediately ''downloads the new document data back to the browser'', which prompts you to either open the downloaded document for viewing or save it to your local hard drive. Once the document has been stored on your filesystem, you can open that copy in your browser and work offline with full access to all TiddlyWiki features.
Important note for users of Internet Explorer's Popup Blocker feature...
>{{block{
//The default security settings of IE's "Popup Blocker" feature will warn you whenever an attempt is made to download a file in response to a scripted action such as the internal javascript processing performed by SaveFromWebPlugin. However, if you then click IE's yellow warning message and select the 'download this file...' menu command, this will also cause IE to attempt a 'page transition' away from the currently loaded TiddlyWiki document... but, because there are unsaved changes in the document, you will first receive a confirmation message, allowing you to cancel the page transition. Regrettably, this also prevents the download from succeeding. Unfortunately, if you permit the page transition to occur, then your TiddlyWiki document is immediately reloaded and all the unsaved tiddler changes are discarded... and the download still fails to complete!//
''__To permit SaveFromWebPlugin to function properly with Internet Explorer, you will need to adjust the "download" security setting...__''
#From the ''Tools > Internet Options > Security'' tab,
#Select the "Internet" security zone (or what ever zone you are using to view the remote document)
#Press the "Custom level..." button
#In the "Settings" listbox, scroll to the "Downloads" section
#''ENABLE "automatic prompting for downloads"''(the first setting in the section)
#Press OK to accept the new settings.
}}}
<<<
!!!!!Configuration
> see [[SaveFromWebConfig]]
!!!!! Server script installation
<<<
On your web server, in the same directory as your published document, create a file called ''{{{savefromweb.php}}}'', containing the following PHP server-side script. //(note: you can actually give this script any name you like, and place it at //any// URL, even one that is on a different domain from the document you are saving. However, to do so you must specify the server-side script location using the plugin's configuration settings//
//{{{
<?php
// savefromweb.php
// Author: Eric L. Shulman / ELS Design Studios
// Source: http://www.TiddlyTools.com/savefromweb.php
// License: http://www.TiddlyTools.com/#LegalStatements
// Usage: install the php script on the server in the same directory as your TiddlyWiki document(s)
// This script acts as a 'reflector', so that any contents sent to it (via form POST) will
// be sent back to the browser as a binary file. The browser then prompts you to
// save the content to a local file. Because this process uses the browser's built-in
// download-and-save/open handler, it does not require security permissions to access
// the local filesystem.
$args=$_POST;
header('Pragma: private');
header('Cache-control: private, must-revalidate');
header('Content-type: application/binary; charset="UTF-8"');
header('Content-disposition: attachment; filename="'.$args['filename'].'"');
$c=$args['contents'];
$c=str_replace("\\'","'",$c); // decode single-quotes
$c=str_replace("\\\"","\"",$c); // decode double-quotes
$c=str_replace("\\\\","\\",$c); // decode backslashes
$c=str_replace("\r\n","\n",$c); // change CRLF to LF
print $c;
?>
//}}}
<<<
!!!!!Direct filesystem access (browser security permissions)
<<<
Although sending the merged document data from browser to server and back again allows it to be saved to your filesystem without requiring you to extensively re-configure your browser's built-in security protections, it also increases the overall processing time because the document's data is actually being transmitted //three// times: it is first retrieved from the remote server to get the TiddlyWiki core source; then, after merging with the updated tiddler data, it is sent back to the server, which immediately 'reflects' it back to the browser for final handling by the built-in "file download" interface.
However, ''if you are accessing a "trusted site"'' (perhaps on a server within a secure private network), depending upon the specific options provided by your browser, ''you may be able to eliminate the round-trip processing by authorizing the appropriate filesystem security permissions in your browser''. When filesystem access has been permitted, instead of making the round trip with the merged core+tiddler data, the plugin will directly prompt you for a destination path/file, using your computer's "native" path/file selection interface, and then write new the TiddlyWiki document data directly to the indicated location on your local file system.
FireFox users: please see [[FAQ_BrowserSecurity]] for information on configuring your browser to permit remote filesystem access from trusted sites
<<<
!!!!!Revisions
<<<
2008.09.29 [1.3.1] in saveFromWeb(), do NOT convert UTF8 to Unicode when merging retrieved source for submission to server-side reflector script. Fixes mangling of international characters and symbols.
2008.01.08 [*.*.*] plugin size reduction: documentation moved to SaveFromWebPluginInfo
2007.08.08 [1.3.0] added caching of the downloaded TW core source code so it only has to be retrieved once.
2007.08.08 [1.2.5] added an option to 'pre-fetch' the TW core when plugin is initialized, so that the download-and-cache will be performed, in background, each time the document is loaded/re-loaded. Also, added option to allow attempt to use direct filesystem access (bypassing the round-trip through the server-side reflector script) so you can save a remote file to your local filesystem, even if the connection to the network is dropped after the document was loaded into the browser. If local filesystem permissions are not granted, the plugin will still attempt to use the server-side reflector script as a fallback.
2007.08.07 [1.2.0] removed 'download only' optimization: when a document is unchanged, instead of performing a simple download from server, the plugin now performs a full 'round-trip' process (i.e., download the TW source from a server, merge with current tiddlers, and then upload merged document and reflect back as a binary file). Although the round-trip takes longer, it does permit the reflector script to be located ANYWHERE on the net, at ANY valid URL, rather than having to be placed on the same server and in the same directory as the remote document. This should permit online services such as TiddlySpot to support SaveFromWebPlugin using a single hosted copy of the reflector script that can be shared by all users.
2007.07.27 [1.1.1] new documentation and code cleanup
2007.07.26 [1.1.0] re-wrote to support savefromweb.php remote "reflector" script. Allows use of browser's native download dialog to receive file as a fallback alternative to using local filesystem I/O (which would require additional security permissions)
2007.06.27 [1.0.1] in saveFromWeb(), pass content from server through convertUnicodeToUTF8() before writing to file.
2007.06.26 [1.0.0] initial release
<<<
/***
|Name|SinglePageModePluginInfo|
|Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
|Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
|Version|2.9.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|documentation|
|Requires||
|Overrides||
|Description|Documentation for SinglePageModePlugin|
Normally, as you click on the links in TiddlyWiki, more and more tiddlers are displayed on the page. The order of this tiddler display depends upon when and where you have clicked. Some people like this non-linear method of reading the document, while others have reported that when many tiddlers have been opened, it can get somewhat confusing. SinglePageModePlugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one item displayed at a time.
!!!!!Usage
<<<
When the plugin is enabled, only one tiddler will be displayed at a time and the browser window's titlebar is updated to include the current tiddler title. The browser's location URL is also updated with a 'permalink' for the current tiddler so that it is easier to create a browser 'bookmark' for the current tiddler. Alternatively, even when displaying multiple tiddlers //is// permitted, you can still reduce the potential for confusion by forcing tiddlers to always open at the top (or bottom) of the page instead of being displayed following the tiddler containing the link that was clicked.
<<<
!!!!!Configuration
<<<
<<option chkSinglePageMode>> Display one tiddler at a time
><<option chkSinglePagePermalink>> Automatically permalink current tiddler
><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
<<option chkTopOfPageMode>> Open tiddlers at the top of the page
<<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
<<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)
Notes:
* {{block{
The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}. You can also use {{{SPM:expression}}}, where 'expression' is any javascript statement that evaluates to true or false. This allows you to create hard-coded links in other documents that can selectively enable/disable the use of this option based on various programmatic conditions, such as the current username. For example, using
{{{#SPM:config.options.txtUserName!="SomeName"}}}
enables 'one tiddler at a time' display for all users //other than// "~SomeName")}}}
* If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
* When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
<<<
!!!!!Revisions
<<<
2008.06.12 [2.9.5] corrected 'scroll to top of page' logic in auto-scroll handling
2008.06.11 [2.9.4] added chkSinglePageKeepEditedTiddlers option
2008.06.05 [2.9.3] in displayTiddler(), bypass single/top/bottom mode handling if startingUp. Allows multiple tiddlers to be displayed during startup processing (e.g., #story:DefaultTiddlers), even if single/top/bottom mode is enabled.
2008.04.18 [2.9.2] in displayTiddler() and checkLastURL(), handling for Unicode in tiddler titles (remove explicit conversion between Unicode and UTF, as this is apparently done automatically by encode/decodeURIComponent, resulting in double-encoding!
2008.04.08 [2.9.1] don't automatically add options to AdvancedOptions shadow tiddler
2008.04.02 [2.9.0] in displayTiddler(), when single-page mode is in use and a tiddler is being edited, ask for permission to save-and-close that tiddler, instead of just leaving it open.
2008.03.29 [2.8.3] in displayTiddler(), get title from tiddler object (if needed). Fixes errors caused when calling function passes a tiddler *object* instead of a tiddler *title*
2008.03.14 [2.8.2] in displayTiddler(), if editing specified tiddler, just move it to top/bottom of story *without* re-rendering (prevents discard of partial edits).
2008.03.06 [2.8.1] in paramifier handler, start 'checkURL' timer if chkSinglePageMode is enabled
2008.03.06 [2.8.0] added option, {{{config.options.chkSinglePageKeepFoldedTiddlers}}}, so folded tiddlers won't be closed when using single-page mode. Also, in checkURL(), if hash is a ''permaview'' (e.g., "#foo bar baz"), then display multiple tiddlers rather than attempting to display "foo bar baz" as a single tiddler
2008.03.05 [2.7.0] added support for "SPM:" URL paramifier
2008.03.01 [2.6.0] in hijack of displayTiddler(), added 'title' argument to closeAllTiddlers() so that target tiddler isn't closed-and-reopened if it was already displayed. Also, added config.options.chkSinglePageAutoScrolloption to bypass automatic 'scroll into view' logic (note: core still does it's own ensureVisible() handling)
2007.12.22 [2.5.3] in checkLastURL(), use decodeURIComponent() instead of decodeURI so that tiddler titles with commas (and/or other punctuation) are correctly handled.
2007.10.26 [2.5.2] documentation cleanup
2007.10.08 [2.5.1] in displayTiddler(), when using single-page or top-of-page mode, scrollTo(0,0) to ensure that page header is in view.
2007.09.13 [2.5.0] for TPM/BPM modes, don't force tiddler to redisplay if already shown. Allows transition between view/edit or collapsed/view templates, without repositioning displayed tiddler.
2007.09.12 [2.4.0] added option to disable automatic permalink feature. Also, Safari is now excluded from permalinking action to avoid bug where tiddlers don't display after hash is updated.
2007.03.03 [2.3.1] fix typo when adding BPM option to AdvancedOptions (prevented checkbox from appearing)
2007.03.03 [2.3.0] added support for BottomOfPageMode (BPM) based on request from DaveGarbutt
2007.02.06 [2.2.3] in Story.prototype.displayTiddler(), use convertUnicodeToUTF8() for correct I18N string handling when creating URL hash string from tiddler title (based on bug report from BidiX)
2007.01.08 [2.2.2] use apply() to invoke hijacked core functions
2006.07.04 [2.2.1] in hijack for displayTiddlers(), suspend TPM as well as SPM so that DefaultTiddlers displays in the correct order.
2006.06.01 [2.2.0] added chkTopOfPageMode (TPM) handling
2006.02.04 [2.1.1] moved global variable declarations to config.* to avoid FireFox 1.5.0.1 crash bug when assigning to globals
2005.12.27 [2.1.0] hijack displayTiddlers() so that SPM can be suspended during startup while displaying the DefaultTiddlers (or #hash list). Also, corrected initialization for undefined SPM flag to "false", so default behavior is to display multiple tiddlers
2005.12.27 [2.0.0] Update for TW2.0
2005.11.24 [1.1.2] When the back and forward buttons are used, the page now changes to match the URL. Based on code added by Clint Checketts
2005.10.14 [1.1.1] permalink creation now calls encodeTiddlyLink() to handle tiddler titles with spaces in them
2005.10.14 [1.1.0] added automatic setting of window title and location bar ('auto-permalink'). feature suggestion by David Dickens.
2005.10.09 [1.0.1] combined documentation and code in a single tiddler
2005.08.15 [1.0.0] Initial Release
<<<
@@color(darkblue):font-size(1.8em):Salman Avestimehr@@
/*{{{*/
body{
background: #f9f9f9 url(avestimehr5.jpg) no-repeat top left;
}
#titleLine{
display: block;
background: transparent url(wiki.png) no-repeat 18px -7px;
_background: transparent;
height: 120px;
_height: 135px;
width: 150px;
color:#BF2323;
border: 1px;
padding: 50px;
margin: 0;
}
* html #titleLine{
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='wiki.png',sizingMethod='scale');
}
#contentWrapper #siteTitle a{
display: inline;
font-weight: bold;
color:#BF2323;
font-size: 13px;
}
#siteTitle, #mainMenu{
position: static;
}
#contentWrapper #sidebar{
top: 0;
left: 0;
}
#displayArea {
margin: 0 0 0 17em;
}
#messageArea{
position: fixed;
top: 0;
right: 0;
font-size: 10px;
border: 1px solid #aaa;
background: #fff;
z-index: 25;
}
#messageArea a:link{
color:#BF2323;
text-decoration: none;
}
#messageArea a:hover{
text-decoration: underline;
}
.viewer{
background: #fff;
border: 1px solid #aaa;
padding: 1em;
margin: 0;
}
.body{
padding: 1px;
}
.title{
background: #fff;
border: 1px solid #aaa;
display: inline;
margin-left: .5em;
padding: 2px .5em;
border-bottom: 0;
font-weight: bold;
color: #BF2323;
font-size: 1.3em;
}
.toolbar{
visibility: hidden;
display: inline;
padding: 0;
font-family: sans-serif;
}
.toolbar a.button:link,.toolbar a.button:visited{
background: #fff;
border: 1px solid #aaa;
color:#BF2323;
font-size: 11px;
padding-bottom: 0;
margin-right: .25em;
}
.selected .toolbar {
visibility: visible;
}
/* TiddlyPedia was Created by Clinton Checketts based on the Monobook skin of Wikipedia */
#contentWrapper .toolbar .button:hover{
border-bottom: 1px solid #fff;
background: #fff;
color:#BF2323;
}
.toolbar a.button:hover{
border-bottom: 1px solid #fff;
background: #fff;
color:#BF2323;
}
#displayArea .viewer a,a.button:link,a.button:visited,
a.tiddlyLink:link,a.tiddlyLink:visited,
#sidebarOptions .sliderPanel a{
color:#BF2323;
background: transparent;
border: 0;
}
.viewer a:hover,a.button:hover,a.button:active,
a.tiddlyLink:hover,a.tiddlyLink:active,
.viewer a.button:hover,
#sidebarOptions .sliderPanel a:hover{
color:#BF2323;
background: transparent;
text-decoration: underline;
}
#mainMenu{
font-family: sans-serif;
text-align: left;
font-size: 17px;
width: 100%;
margin: 0;
padding: 10;
}
#mainMenu h1{
font-size: 17px;
font-weight: normal;
padding: 0;
margin: 0;
background: transparent;
}
#mainMenu ul{
font-size: 15px;
border: 1px solid #aaa;
padding: .25em 0;
margin: 0;
list-style-type: square;
list-style-image: url(bullet.gif);
background: #fff;
width: 100%;
}
#mainMenu li{
margin: 0 0 0 2em;
padding: 0;
}
#contentWrapper #mainMenu a:link,#contentWrapper #mainMenu a:visited{
color:#BF2323;
padding: 0;
margin: 0;
background: transparent;
}
#mainMenu .externalLink {
text-decoration: none;
}
#mainMenu .externalLink:hover {
text-decoration: underline;
}
#sidebar{
padding: .5em;
font-family: sans-serif;
}
#sidebarOptions{
border: 1px solid #aaa;
background: #fff;
margin-top: .5em;
width: 100%;
}
#sidebar .sliderPanel{
margin: 0;
}
#contentWrapper #sidebarOptions .button,#contentWrapper #sidebarOptions .button:hover{
color:#BF2323;
padding: .1em 0 .1em 2em;
background: transparent url(bullet.gif) 10px -2px no-repeat;
}
#sidebarOptions input{
width: 80%;
margin: 0 .5em;
}
#sidebarTabs{
background: #fff;
margin-top: .5em;
width: 100%;
}
#sidebarTabs .tabContents,#sidebarTabs .tabContents .tabContents{
border: 1px solid #aaa;
background: #fff;
}
#sidebarTabs .tabSelected,#sidebarTabs .tabcontents .tabSelected {
background: #fff;
border: 1px solid #aaa;
border-bottom: 0;
cursor: default;
padding-bottom: 3px;
color: #000;
}
#sidebarTabs .tabUnselected,#sidebarTabs .tabContents .tabUnselected{
background: #aaa;
padding-bottom: 0;
color: #000;
}
#contentWrapper #sidebarTabs .tiddlyLink,#contentWrapper #sidebarTabs .button,
#contentWrapper #sidebarTabs a.tiddlyLink:hover,#contentWrapper #sidebarTabs a.button:hover{
background: transparent;
color:#BF2323;
}
.footer{
margin: -1em 0 1em 0;
}
.footer .button:hover,.editorFooter .button:hover{
background: transparent;
color:#BF2323;
border-bottom: 1px solid #002bb8;
}
#popup{
background: #e9e9e9;
color: #000;
}
#popup hr{
border-color: #aaa;
background-color: #aaa;
}
#popup a{
color: #000;
}
#popup a:hover,#contentWrapper #sidebarTabs #popup a:hover{
background: #666;
color: #fff;
text-decoration: none;
}
#displayArea .tiddler a.tiddlyLinkNonExisting{
color: #ba0000;
}
#displayArea .tiddler a.externalLink{
text-decoration: none;
color:#BF2323;
padding-right: 0;
background: transparent url(external.png) 100% 50% no-repeat;
}
#displayArea .tiddler a.externalLink:hover{
text-decoration: underline;
}
.viewer pre{
background: #e9e9e9;
border: 1px solid #666;
}
.viewer h1, .viewer h2, .viewer h3, .viewer h4, .viewer h5, .viewer h6{
background: transparent;
border-bottom: .2em solid #aaa;
}
#sidebar .sliderPanel{
background: #e9e9e9;
}
#sidebar .sliderPanel input{width: auto;}
.tagged, .tagging, .listTitle{
float: none;
display: inline;
}
.tagged li, .tagging li,
.tagged ul, .tagging ul{
display: inline;
}
.firstletter{ float:left; width:0.75em; font-size:400%; font-family:times,arial; line-height:60%; }
.textcenter {text-align:center;}
.textright {text-align:right;}
.textjustify {text-align:justify;}
.textleft {text-align:left;}
/*}}}*/
!!PhD Thesis
{{alignBullets {
*@@color(darkblue):"Wireless Network Information Flow: A Deterministic Approach"@@, Salman Avestimehr, Ph.D. Thesis, UC Berkeley, 2008.
**For a quick overview of our deterministic approach to wireless netwrok information theory please take a look at [[this page|Deterministic Approach]] and [[these slides|./papers/DetApproachSlides.pdf]].
!!MS Thesis
*@@color(darkblue):"Outage Capacity of the Fading Relay Channel in the Low SNR Regime"@@, Salman Avestimehr, M.Sc. Thesis, UC Berkeley, 2005. [[PDF|./papers/MSTHESIS.pdf]]
<!--{{{-->
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler jump'></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>
<!--}}}-->
/%
|Name|VisitCounter|
|Source|http://www.TiddlyTools.com/#VisitCounter|
|Version|2.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|script|
|Requires|InlineJavascriptPlugin|
|Overrides||
|Description|use cookies to track/show private, personal visit counter and timestamp of last visit|
This script tracks and displays a personal, private counter and the timestamps for your first visit, your most recent visit, and the total number of times you have visited a document. This information is stored in local cookies, and is ONLY available for display in YOUR browser. This data is not NOT tracked or aggregated across users, nor relayed or reported to anyone other than yourself, EVER.
Usage:
{{{<<tiddler VisitCounter with: counterID firsttimegreeting>>}}}
where:
* counterID (optional) - specifies a suffix to add to the visit tracking cookies for this document (enables tracking of multiple documents on a single domain, such as file://).
* firsttimegreeting (optional) - message to display upon first visit to the document. Subsequent visits report last visit timestamp and total visit count.
Cookies used to track your visit information:
txtFirstVisit+id, txtLastVisit+id, txtVisitCount+id
The script also defines global config values that may be referenced later by other scripts:
config.firstVisit, config.lastVisit, config.visitCount
!!!!!Revisions
<<<
2008.07.01 [2.1.0] simplified to inline script
2007.07.26 [2.0.0] re-written as plugin
2007.05.02 [1.0.0] initial release (as inline script, VisitCounter)
!end revisions
!outputFormat
This is your <html><hide linebreaks><a href="javascript:;"
title="Reset personal visit counter"
onclick="if (!confirm('Are you sure you want to reset your personal visit counter?')) return false;
config.visitCount=config.options['txtVisitCount%0']=1;
config.firstVisit=config.options['txtFirstVisit%0']=new Date();
config.lastVisit=config.options['txtLastVisit%0']=new Date();
saveOptionCookie('txtVisitCount%0');
saveOptionCookie('txtFirstVisit%0');
saveOptionCookie('txtLastVisit%0');
var t=story.findContainingTiddler(this);
if(t)story.refreshTiddler(t.getAttribute('tiddler'),null,true);
">''%1 visit''</a></html> since %2. Your last visit was on %3.
!end outputFormat
%/<script>
var out="";
var id="";
if ("$1"!="$"+"1") id="_$1";
var greeting="";
if ("$2"!="$"+"2") greeting="$2";
if (config.firstVisit==undefined) { // only do this once per session
// create the 'first visit' timestamp cookie
if (!config.options["txtFirstVisit"+id] || !config.options["txtFirstVisit"+id].length) {
config.options["txtFirstVisit"+id]=new Date();
saveOptionCookie("txtFirstVisit"+id);
}
config.firstVisit=config.options["txtFirstVisit"+id];
}
if (config.lastVisit==undefined) { // only do this once per session
config.lastVisit=config.options["txtLastVisit"+id];
if (config.lastVisit==undefined) config.lastVisit="";
config.options["txtLastVisit"+id]=new Date();
saveOptionCookie("txtLastVisit"+id);
var c=config.options["txtVisitCount"+id]?parseInt(config.options["txtVisitCount"+id]):0;
config.visitCount=config.options["txtVisitCount"+id]=c+1;
saveOptionCookie("txtVisitCount"+id);
}
// get and format # of visits
var count=config.options["txtVisitCount"+id]; if (!count) count=1;
var wordmap=['---','first','second','third','fourth','fifth','sixth','seventh','eighth','ninth'];
var suffixmap=['th','st','nd','rd','th','th','th','th','th','th'];
var digits=count.toString().substr(count.toString().length-2,2);
if (count<10) count=wordmap[count];
else if (digits>=10&&digits<=13) count=count+'th';
else count=count+suffixmap[digits.substr(1,1)];
var out=greeting; // initial greeting for first visit only
if (config.lastVisit.length) {
var first=new Date(config.firstVisit).formatString("MMM DDth YYYY");
var last=new Date(config.lastVisit).formatString("MMM DDth YYYY at 0hh12:0mm:0ss am");
out=store.getTiddlerText("VisitCounter##outputFormat").format([id,count,first,last])
}
return out;
</script>
/***
|!''Name:''|!easyFormat|
|''Description:''|the format command format selection according to your choice|
|''Version:''|0.1.0|
|''Date:''|13/01/2007|
|''Source:''|[[TWkd|http://yann.perrin.googlepages.com/twkd.html#easyFormat]]|
|''Author:''|[[Yann Perrin|YannPerrin]]|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.x|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
|''Requires:''|@@color:red;''E.A.S.E''@@|
***/
//{{{
config.commands.format = new TWkd.Ease('Format','format selection accordingly to chosen mode');
config.commands.format.addMode({
name:'Bold',
tooltip:'turns selection into bold text',
operation:function(){
config.commands.format.putInPlace("''"+TWkd.context.selection.content+"''",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Italic',
tooltip:'turns selection into italic text',
operation:function(){
config.commands.format.putInPlace("//"+TWkd.context.selection.content+"//",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Underlined',
tooltip:'turns selection into underlined text',
operation:function(){
config.commands.format.putInPlace("__"+TWkd.context.selection.content+"__",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Strikethrough',
tooltip:'turns selection into striked text',
operation:function(){
config.commands.format.putInPlace("--"+TWkd.context.selection.content+"--",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Superscript',
tooltip:'turns selection into superscript',
operation:function(){
config.commands.format.putInPlace("^^"+TWkd.context.selection.content+"^^",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Subscript',
tooltip:'turns selection into subscript',
operation:function(){
config.commands.format.putInPlace("~~"+TWkd.context.selection.content+"~~",TWkd.context.selection);
}
});
config.commands.format.addMode({
name:'Highlight',
tooltip:'highlight selection',
operation:function(){
config.commands.format.putInPlace("@@"+TWkd.context.selection.content+"@@",TWkd.context.selection);
}
});
//}}}